From f3b0a716e68915dbe4a295625da5e325a1d22fe9 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 3 Nov 2015 21:25:40 +0100 Subject: [PATCH 001/268] Add build folders to .gitignore file --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 1d085f5b..c0e3a6ff 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ docs/_build unittests/temp unittests/data/pygccxml.cache .idea +dist +build +pygccxml.egg-info From f589b3295d52d5c02a1e38f5acacddf908cd62bd Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 3 Nov 2015 23:21:29 +0100 Subject: [PATCH 002/268] Fix performance test --- unittests/test_performance.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/unittests/test_performance.py b/unittests/test_performance.py index 3dcc67f6..45011ab1 100644 --- a/unittests/test_performance.py +++ b/unittests/test_performance.py @@ -9,7 +9,7 @@ import hotshot.stats import autoconfig from pygccxml import parser -from pyggcxml import declarations +from pygccxml import declarations dcache_file_name = os.path.join(autoconfig.data_directory, 'pygccxml.cache') if os.path.exists(dcache_file_name): @@ -23,7 +23,7 @@ def test_on_windows_dot_h(): dcache = parser.file_cache_t(dcache_file_name) reader = parser.source_reader_t( parser.xml_generator_configuration_t( - xml_generator_path=autoconfig.xml_generator_path), + xml_generator_path=autoconfig.generator_path), dcache) reader.read_file(windows_header) dcache.flush() @@ -34,7 +34,7 @@ def test_on_windows_dot_h(): dcache = parser.file_cache_t(dcache_file_name) reader = parser.source_reader_t( parser.xml_generator_configuration_t( - xml_generator_path=autoconfig.xml_generator_path), + xml_generator_path=autoconfig.generator_path), dcache) reader.read_file(windows_header) clock_now = time.clock() @@ -52,7 +52,7 @@ def test_source_on_include_std_dot_hpp(): dcache = parser.file_cache_t(dcache_file_name) reader = parser.source_reader_t( parser.xml_generator_configuration_t( - xml_generator_path=autoconfig.xml_generator_path), + xml_generator_path=autoconfig.generator_path), dcache) reader.read_file(include_std_header) dcache.flush() @@ -63,7 +63,7 @@ def test_source_on_include_std_dot_hpp(): dcache = parser.file_cache_t(dcache_file_name) reader = parser.source_reader_t( parser.xml_generator_configuration_t( - xml_generator_path=autoconfig.xml_generator_path), + xml_generator_path=autoconfig.generator_path), dcache) reader.read_file(include_std_header) clock_now = time.clock() @@ -80,7 +80,7 @@ def test_project_on_include_std_dot_hpp(): dcache = parser.file_cache_t(dcache_file_name) reader = parser.project_reader_t( parser.xml_generator_configuration_t( - xml_generator_path=autoconfig.xml_generator_path), + xml_generator_path=autoconfig.generator_path), dcache) reader.read_files([include_std_header]) dcache.flush() @@ -91,7 +91,7 @@ def test_project_on_include_std_dot_hpp(): dcache = parser.file_cache_t(dcache_file_name) reader = parser.project_reader_t( parser.xml_generator_configuration_t( - xml_generator_path=autoconfig.xml_generator_path), + xml_generator_path=autoconfig.generator_path), dcache) reader.read_files([include_std_header]) clock_now = time.clock() @@ -104,7 +104,7 @@ def profile_project(): 'include_std.hpp') reader = parser.project_reader_t( parser.xml_generator_configuration_t( - xml_generator_path=autoconfig.xml_generator_path)) + xml_generator_path=autoconfig.generator_path)) reader.read_files([include_std_header]) @@ -113,7 +113,7 @@ def profile_project2(): include_std_header = r"D:\Program Files\Microsoft Visual Studio .NET " + he reader = parser.project_reader_t( parser.xml_generator_configuration_t( - xml_generator_path=autoconfig.xml_generator_path)) + xml_generator_path=autoconfig.generator_path)) reader.read_files([include_std_header]) @@ -122,7 +122,7 @@ def test_on_big_file(file_name, count): for i in range(count): reader = parser.project_reader_t( parser.xml_generator_configuration_t( - xml_generator_path=autoconfig.xml_generator_path)) + xml_generator_path=autoconfig.generator_path)) decls = reader.read_files([parser.create_gccxml_fc(file_name)]) global_ns = declarations.get_global_namespace(decls) global_ns.init_optimizer() @@ -132,7 +132,7 @@ def parse_big_file(): path = os.path.join(autoconfig.data_directory, 'big.xml') reader = parser.project_reader_t( parser.xml_generator_configuration_t( - xml_generator_path=autoconfig.xml_generator_path)) + xml_generator_path=autoconfig.generator_path)) reader.read_files([parser.create_gccxml_fc(path)]) reader.read_files([parser.create_gccxml_fc(path)]) reader.read_files([parser.create_gccxml_fc(path)]) From ef9bbec59452092c470f8defdcec3323bda7ec39 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 3 Nov 2015 23:21:55 +0100 Subject: [PATCH 003/268] Remove unused function --- unittests/test_performance.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/unittests/test_performance.py b/unittests/test_performance.py index 45011ab1..41d1f405 100644 --- a/unittests/test_performance.py +++ b/unittests/test_performance.py @@ -128,16 +128,6 @@ def test_on_big_file(file_name, count): global_ns.init_optimizer() -def parse_big_file(): - path = os.path.join(autoconfig.data_directory, 'big.xml') - reader = parser.project_reader_t( - parser.xml_generator_configuration_t( - xml_generator_path=autoconfig.generator_path)) - reader.read_files([parser.create_gccxml_fc(path)]) - reader.read_files([parser.create_gccxml_fc(path)]) - reader.read_files([parser.create_gccxml_fc(path)]) - - if __name__ == "__main__": # test_on_windows_dot_h() From 3f671370d05aa6e0c5f5f7c30aad9875d11958da Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 3 Nov 2015 23:23:18 +0100 Subject: [PATCH 004/268] Add typical xml file (from the ITK project) and test performance on it --- unittests/data/itkImage.xml | 29174 ++++++++++++++++++++++++++++++++ unittests/test_performance.py | 2 +- 2 files changed, 29175 insertions(+), 1 deletion(-) create mode 100644 unittests/data/itkImage.xml diff --git a/unittests/data/itkImage.xml b/unittests/data/itkImage.xml new file mode 100644 index 00000000..9508992e --- /dev/null +++ b/unittests/data/itkImage.xml @@ -0,0 +1,29174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/unittests/test_performance.py b/unittests/test_performance.py index 41d1f405..79adfb78 100644 --- a/unittests/test_performance.py +++ b/unittests/test_performance.py @@ -135,7 +135,7 @@ def test_on_big_file(file_name, count): # test_project_on_include_std_dot_hpp() print('running') prof = hotshot.Profile('parser.prof') - prof.runcall(lambda: test_on_big_file('big2.xml', 1)) + prof.runcall(lambda: test_on_big_file('itkImage.xml', 1)) stats = hotshot.stats.load("parser.prof") stats.sort_stats('time', 'calls') stats.print_stats(30) From c24da0b5131e1571d81349d453e088b2be7e8e39 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 3 Nov 2015 23:25:42 +0100 Subject: [PATCH 005/268] Add CastXML keyword to setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 989f5d7c..9ddd7797 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ url="https://github.com/gccxml/pygccxml", download_url="https://github.com/gccxml/pygccxml/archive/master.zip", license="Boost", - keywords="C++, declaration parser, gccxml", + keywords="C++, declaration parser, CastXML, gccxml", packages=["pygccxml", "pygccxml.declarations", "pygccxml.parser", From e72e2f4239f044dbfa7e321cb25b06fe579efc59 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 5 Nov 2015 22:35:56 +0100 Subject: [PATCH 006/268] Add .prof files to .gitingore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c0e3a6ff..65d55225 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ unittests/data/pygccxml.cache dist build pygccxml.egg-info +*.prof From 32f42239a437a68ca99d1aa861b4c89546aac1c1 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 5 Nov 2015 23:06:20 +0100 Subject: [PATCH 007/268] Move performance test to a separate folder These tests should not be covered as they are not run by the test suite. They are mostly there when working on debugging performance problems --- .coveragerc | 3 +++ unittests/{ => misc}/profile_parser.py | 0 unittests/{ => misc}/test_performance.py | 0 unittests/{ => misc}/timeit_test_parser.py | 0 4 files changed, 3 insertions(+) rename unittests/{ => misc}/profile_parser.py (100%) rename unittests/{ => misc}/test_performance.py (100%) rename unittests/{ => misc}/timeit_test_parser.py (100%) diff --git a/.coveragerc b/.coveragerc index 788dbdbc..4e650856 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,5 +1,8 @@ [run] source = pygccxml,docs/example,unittests +# unittest/misc contains some tests that are just there for debugging +# purposes and which do not need to be covered. +omit = unittests/misc parallel = True [report] diff --git a/unittests/profile_parser.py b/unittests/misc/profile_parser.py similarity index 100% rename from unittests/profile_parser.py rename to unittests/misc/profile_parser.py diff --git a/unittests/test_performance.py b/unittests/misc/test_performance.py similarity index 100% rename from unittests/test_performance.py rename to unittests/misc/test_performance.py diff --git a/unittests/timeit_test_parser.py b/unittests/misc/timeit_test_parser.py similarity index 100% rename from unittests/timeit_test_parser.py rename to unittests/misc/timeit_test_parser.py From 15a7241ecefd67496e022b0f9e14e6f7e232dafa Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 5 Nov 2015 23:26:58 +0100 Subject: [PATCH 008/268] Use the "is not" syntax --- pygccxml/declarations/calldef.py | 3 +-- pygccxml/declarations/decl_printer.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index b41bfa9a..aae095fc 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -354,8 +354,7 @@ def overloads(self): # finding all functions with the same name return self.parent.calldefs( name=self.name, - function=lambda decl: not ( - decl is self), + function=lambda decl: decl is not self, allow_empty=True, recursive=False) diff --git a/pygccxml/declarations/decl_printer.py b/pygccxml/declarations/decl_printer.py index 6e706dc4..4abd82d6 100644 --- a/pygccxml/declarations/decl_printer.py +++ b/pygccxml/declarations/decl_printer.py @@ -339,7 +339,7 @@ def print_hierarchy(hierarchy_type, classes, curr_level): self.INDENT_SIZE + access.ljust(self.JUSTIFY) + os.linesep) - if not (None is class_.is_virtual): + if class_.is_virtual is not None: is_virtual = 'virtual inheritance: ' + \ "'%s'" % str(class_.is_virtual) self.writer(' ' * From d32b4e60833cca7ce4f454208499366506c4eb79 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 5 Nov 2015 23:45:00 +0100 Subject: [PATCH 009/268] Use the with context syntax to open files Add b mode to these files --- pygccxml/declarations/decl_printer.py | 18 +++++++-------- pygccxml/parser/declarations_cache.py | 17 +++++++------- pygccxml/parser/source_reader.py | 8 +++---- unittests/file_cache_tester.py | 15 +++++------- .../project_reader_correctness_tester.py | 23 +++++++++---------- 5 files changed, 38 insertions(+), 43 deletions(-) diff --git a/pygccxml/declarations/decl_printer.py b/pygccxml/declarations/decl_printer.py index 4abd82d6..8b0c95b5 100644 --- a/pygccxml/declarations/decl_printer.py +++ b/pygccxml/declarations/decl_printer.py @@ -477,8 +477,7 @@ def print_declarations( decls, detailed=True, recursive=True, - writer=lambda x: sys.stdout.write( - x + os.linesep), + writer=lambda x: sys.stdout.write(x + os.linesep), verbose=True): """ print declarations tree rooted at each of the included nodes. @@ -495,14 +494,15 @@ def print_declarations( algorithm.apply_visitor(prn, d) -def dump_declarations(decls, fpath): +def dump_declarations(declarations, file_path): """ - dump declarations tree rooted at each of the included nodes to the file + Dump declarations tree rooted at each of the included nodes to the file - :param decls: either a single :class:declaration_t object or list + :param declarations: either a single :class:declaration_t object or a list of :class:declaration_t objects - :param fpath: file name + :param file_path: path to a file + """ - fobj = open(fpath, 'w+') - print_declarations(decls, writer=fobj.write) - fobj.close() + + with open(file_path, "wb+") as f: + print_declarations(declarations, writer=f.write) diff --git a/pygccxml/parser/declarations_cache.py b/pygccxml/parser/declarations_cache.py index a1a805e2..880629f5 100644 --- a/pygccxml/parser/declarations_cache.py +++ b/pygccxml/parser/declarations_cache.py @@ -20,13 +20,13 @@ def file_signature(filename): if not os.path.exists(filename): return None # Extend here to use md5 hash for signature - # - This change allows duplicate autogenerated files to be recognized - # return os.path.getmtime( source ) + # - This change allows duplicate auto-generated files to be recognized + sig = hashlib.md5() - f = open(filename, 'rb') - buf = f.read() - sig.update(buf) - f.close() + with open(filename, "rb") as f: + buf = f.read() + sig.update(buf) + return sig.hexdigest() @@ -216,9 +216,8 @@ def flush(self): "There are %s removed entries from cache." % num_removed) # Save out the cache to disk - cache_file = open(self.__name, 'w+b') - pickle.dump(self.__cache, cache_file, pickle.HIGHEST_PROTOCOL) - cache_file.close() + with open(self.__name, "w+b") as cache_file: + pickle.dump(self.__cache, cache_file, pickle.HIGHEST_PROTOCOL) def update(self, source_file, configuration, declarations, included_files): """ Update a cached record with the current key and value contents. """ diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index cc1a4020..a52f6b6b 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -400,16 +400,16 @@ def read_string(self, content): """ header_file = pygccxml.utils.create_temp_file_name(suffix='.h') - header_file_obj = open(header_file, 'w+') - header_file_obj.write(content) - header_file_obj.close() - declarations = None + with open(header_file, "wb+") as f: + f.write(content) + try: declarations = self.read_file(header_file) except Exception: pygccxml.utils.remove_file_no_raise(header_file, self.__config) raise pygccxml.utils.remove_file_no_raise(header_file, self.__config) + return declarations def __file_full_name(self, file): diff --git a/unittests/file_cache_tester.py b/unittests/file_cache_tester.py index d6dbdc14..72ed9847 100644 --- a/unittests/file_cache_tester.py +++ b/unittests/file_cache_tester.py @@ -24,16 +24,14 @@ def __init__(self, *args): def touch(self): # Need to change file. - header = open(self.header, "a") - header.write("//touch") - header.close() + with open(self.header, "ab+") as header: + header.write("//touch") def test_update(self): # Save the content of the header file for later - old_header = open(self.header, "r") - content = old_header.read() - old_header.close() + with open(self.header, "rb") as old_header: + content = old_header.read() declarations = parser.parse([self.header], self.config) cache = parser.file_cache_t(self.cache_file) @@ -55,9 +53,8 @@ def test_update(self): # We wrote a //touch in the header file. Just replace the file with the # original content. The touched file would be sometimes commited by # error as it was modified. - new_header = open(self.header, "w") - new_header.write(content) - new_header.close() + with open(self.header, "wb") as new_header: + new_header.write(content) def test_from_file(self): declarations = parser.parse([self.header], self.config) diff --git a/unittests/project_reader_correctness_tester.py b/unittests/project_reader_correctness_tester.py index 4e74b779..87f83a40 100644 --- a/unittests/project_reader_correctness_tester.py +++ b/unittests/project_reader_correctness_tester.py @@ -40,18 +40,17 @@ def __test_correctness_impl(self, file_name): if src_decls != prj_decls: s = src_decls[0] p = prj_decls[0] - sr = open( - os.path.join( - autoconfig.build_directory, file_name + '.sr.txt'), 'w+') - pr = open( - os.path.join( - autoconfig.build_directory, file_name + '.pr.txt'), 'w+') - declarations.print_declarations( - s, writer=lambda l: sr.write(l + os.linesep)) - declarations.print_declarations( - p, writer=lambda l: pr.write(l + os.linesep)) - sr.close() - pr.close() + bdir = autoconfig.build_directory + with open(os.path.join(bdir, file_name + '.sr.txt'), 'wb+') as sr: + with open( + os.path.join(bdir, file_name + '.pr.txt'), + 'wb+') as pr: + + declarations.print_declarations( + s, writer=lambda l: sr.write(l + os.linesep)) + declarations.print_declarations( + p, writer=lambda l: pr.write(l + os.linesep)) + self.fail( "There is a difference between declarations in file %s." % file_name) From ba8a5d3ed04e82a53c1abf25d84137c5a5536896 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 6 Nov 2015 00:03:00 +0100 Subject: [PATCH 010/268] Do not use binary mode with strings, this does not work with python3 Fixes: 'str' does not support the buffer interface --- pygccxml/parser/source_reader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index a52f6b6b..6928d4d1 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -400,7 +400,7 @@ def read_string(self, content): """ header_file = pygccxml.utils.create_temp_file_name(suffix='.h') - with open(header_file, "wb+") as f: + with open(header_file, "w+") as f: f.write(content) try: From 0cf51ed9c27d40b2d57721b9b4ccc6a75b564470 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 7 Nov 2015 13:30:53 +0100 Subject: [PATCH 011/268] Fix path for performance test Also, insert at 1 in sys.path, 0 is for the current file --- unittests/autoconfig.py | 4 ++-- unittests/misc/test_performance.py | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/unittests/autoconfig.py b/unittests/autoconfig.py index 536fc4f8..afe5ccc7 100644 --- a/unittests/autoconfig.py +++ b/unittests/autoconfig.py @@ -13,10 +13,10 @@ data_directory = os.path.join(this_module_dir_path, 'data') build_directory = os.path.join(this_module_dir_path, 'temp') -sys.path.insert(0, os.path.join(os.curdir, '..')) +sys.path.insert(1, os.path.join(os.curdir, '..')) # The tests are run on the parent pygccxml directory, not the one # in site-packages. Insert the directory's path. -sys.path.insert(0, "../pygccxml") +sys.path.insert(1, "../pygccxml") import pygccxml # nopep8 import pygccxml.declarations # nopep8 diff --git a/unittests/misc/test_performance.py b/unittests/misc/test_performance.py index 79adfb78..094fa700 100644 --- a/unittests/misc/test_performance.py +++ b/unittests/misc/test_performance.py @@ -4,13 +4,20 @@ # See http://www.boost.org/LICENSE_1_0.txt import os +import sys import time import hotshot import hotshot.stats -import autoconfig from pygccxml import parser from pygccxml import declarations +this_module_dir_path = os.path.abspath( + os.path.dirname(sys.modules[__name__].__file__)) + +sys.path.insert(1, os.path.join(this_module_dir_path, '../')) + +import autoconfig # nopep8 + dcache_file_name = os.path.join(autoconfig.data_directory, 'pygccxml.cache') if os.path.exists(dcache_file_name): os.remove(dcache_file_name) From 889492c24f7cc10fde6745b37a423c1f7fd4bea4 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 7 Nov 2015 13:31:26 +0100 Subject: [PATCH 012/268] Add .coverage file to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 65d55225..624b27ce 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ dist build pygccxml.egg-info *.prof +.coverage \ No newline at end of file From 917f887c824a06d8fef8cb33085c47c39f0644fa Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 7 Nov 2015 13:42:22 +0100 Subject: [PATCH 013/268] Make sure we import the right pygccxml (not an installed version) in test --- unittests/misc/test_performance.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/unittests/misc/test_performance.py b/unittests/misc/test_performance.py index 094fa700..e05a7fd3 100644 --- a/unittests/misc/test_performance.py +++ b/unittests/misc/test_performance.py @@ -8,15 +8,16 @@ import time import hotshot import hotshot.stats -from pygccxml import parser -from pygccxml import declarations this_module_dir_path = os.path.abspath( os.path.dirname(sys.modules[__name__].__file__)) -sys.path.insert(1, os.path.join(this_module_dir_path, '../')) +sys.path.insert(1, os.path.join(this_module_dir_path, '../../')) +sys.path.insert(2, os.path.join(this_module_dir_path, '../')) -import autoconfig # nopep8 +import autoconfig # nopep8 +from pygccxml import parser # nopep8 +from pygccxml import declarations # nopep8 dcache_file_name = os.path.join(autoconfig.data_directory, 'pygccxml.cache') if os.path.exists(dcache_file_name): From dfe4d0f865dfd6834bacbe357974196cf2002180 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 7 Nov 2015 16:24:18 +0100 Subject: [PATCH 014/268] Fix typo, add information about python 3.5 support in history for v1.7.0 --- README.rst | 2 +- docs/history.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 260adcd1..23947cde 100644 --- a/README.rst +++ b/README.rst @@ -44,7 +44,7 @@ Branches The stable version can be found on the master branch. -The develop branch containes the latest improvements but can be unstable. Pull Requests should be done on the develop branch. +The develop branch contains the latest improvements but can be unstable. Pull Requests should be done on the develop branch. Testing and code coverage ------------------------- diff --git a/docs/history.rst b/docs/history.rst index 46775389..0ed970c1 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -124,6 +124,8 @@ Version 1.7.0 24. [Doc] Small documentation update, moved people list to credits page, added new examples. +25. [Misc] Add Travis unit tests for Python 3.5 + Version 1.6.2 ------------- From 43de3fe187438d0acbdc0c0b48a9275ef2259a9c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 7 Nov 2015 16:24:49 +0100 Subject: [PATCH 015/268] Remove a bunch of unused local variables --- pygccxml/binary_parsers/parsers.py | 2 +- pygccxml/binary_parsers/undname.py | 2 +- pygccxml/declarations/algorithm.py | 1 - pygccxml/declarations/class_declaration.py | 3 +-- pygccxml/declarations/container_traits.py | 7 ------- pygccxml/declarations/pattern_parser.py | 2 +- pygccxml/declarations/type_traits.py | 1 - pygccxml/parser/declarations_cache.py | 2 +- pygccxml/parser/directory_cache.py | 2 +- pygccxml/parser/project_reader.py | 1 - pygccxml/parser/scanner.py | 1 - pygccxml/parser/source_reader.py | 2 +- pygccxml/utils/utils.py | 1 - 13 files changed, 7 insertions(+), 20 deletions(-) diff --git a/pygccxml/binary_parsers/parsers.py b/pygccxml/binary_parsers/parsers.py index 03bd9ba5..b29c8725 100644 --- a/pygccxml/binary_parsers/parsers.py +++ b/pygccxml/binary_parsers/parsers.py @@ -430,7 +430,7 @@ def merge_information(global_ns, fname, runs_under_unittest=False): """high level function - select the appropriate binary file parser and integrates the information from the file to the declarations tree. """ ext = os.path.splitext(fname)[1] - parser = None + if '.dll' == ext: parser = dll_file_parser_t(global_ns, fname) elif '.map' == ext: diff --git a/pygccxml/binary_parsers/undname.py b/pygccxml/binary_parsers/undname.py index 4c0b52f9..6e9a1b33 100644 --- a/pygccxml/binary_parsers/undname.py +++ b/pygccxml/binary_parsers/undname.py @@ -253,7 +253,7 @@ def format_decl(self, decl, hint=None): could be mapped later to the blobs. The valid options are: "msvc" and "nm". """ - name = None + if hint is None: if 'nt' == os.name: hint = 'msvc' diff --git a/pygccxml/declarations/algorithm.py b/pygccxml/declarations/algorithm.py index 2332b132..a908ebfd 100644 --- a/pygccxml/declarations/algorithm.py +++ b/pygccxml/declarations/algorithm.py @@ -286,7 +286,6 @@ def find_all_declarations( """ - decls = [] if recursive: decls = make_flatten(declarations) else: diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index cd918d45..46843f13 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -475,7 +475,7 @@ def remove_declaration(self, decl): :param decl: declaration to be removed :type decl: :class:`declaration_t` """ - container = None + access_type = self.find_out_member_access_type(decl) if access_type == ACCESS_TYPES.PUBLIC: container = self.public_members @@ -497,7 +497,6 @@ def find_out_member_access_type(self, member): """ assert member.parent is self if not member.cache.access_type: - access_type = None if member in self.public_members: access_type = ACCESS_TYPES.PUBLIC elif member in self.protected_members: diff --git a/pygccxml/declarations/container_traits.py b/pygccxml/declarations/container_traits.py index 82981b81..5434f2cc 100644 --- a/pygccxml/declarations/container_traits.py +++ b/pygccxml/declarations/container_traits.py @@ -215,12 +215,10 @@ def erase_hash_allocator(self, cls_name): if len(c_args) < 3: return - default_hash = None default_less = 'std::less' default_equal_to = 'std::equal_to' default_allocator = 'std::allocator' - tmpl = None if 3 == len(c_args): default_hash = 'hash_compare' tmpl = ( @@ -253,7 +251,6 @@ def erase_hashmap_compare_allocator(self, cls_name): cls_name = self.replace_basic_string(cls_name) c_name, c_args = templates.split(cls_name) - default_hash = None if self.unordered_maps_and_sets: default_less_or_hash = 'std::hash' else: @@ -261,9 +258,6 @@ def erase_hashmap_compare_allocator(self, cls_name): default_allocator = 'std::allocator' default_equal_to = 'std::equal_to' - tmpl = None - key_type = None - mapped_type = None if 2 < len(c_args): key_type = c_args[0] mapped_type = c_args[1] @@ -394,7 +388,6 @@ def get_container_or_none(self, type_): utils.loggers.queries_engine.debug( "Container traits: cleaned up search %s" % type_) - cls_declaration = None if isinstance(type_, cpptypes.declarated_t): cls_declaration = type_traits.remove_alias(type_.declaration) elif isinstance(type_, class_declaration.class_t): diff --git a/pygccxml/declarations/pattern_parser.py b/pygccxml/declarations/pattern_parser.py index 67f598c1..7e75be6f 100644 --- a/pygccxml/declarations/pattern_parser.py +++ b/pygccxml/declarations/pattern_parser.py @@ -129,7 +129,7 @@ def join(self, name, args, arg_separator=None): if None is arg_separator: arg_separator = ', ' args = [_f for _f in args if _f] - args_str = '' + if not args: args_str = ' ' elif 1 == len(args): diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index bcc4e788..be605486 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -493,7 +493,6 @@ def is_base_and_derived(based, derived): assert isinstance(based, class_declaration.class_t) assert isinstance(derived, (class_declaration.class_t, tuple)) - all_derived = None if isinstance(derived, class_declaration.class_t): all_derived = ([derived]) else: # tuple diff --git a/pygccxml/parser/declarations_cache.py b/pygccxml/parser/declarations_cache.py index 880629f5..6b54ffe1 100644 --- a/pygccxml/parser/declarations_cache.py +++ b/pygccxml/parser/declarations_cache.py @@ -170,7 +170,7 @@ def __init__(self, name): @staticmethod def __load(file_name): " Load pickled cache from file and return the object. " - cache = None + if os.path.exists(file_name) and not os.path.isfile(file_name): raise RuntimeError( 'Cache should be initialized with valid full file name') diff --git a/pygccxml/parser/directory_cache.py b/pygccxml/parser/directory_cache.py index b04c716e..dd7098d4 100644 --- a/pygccxml/parser/directory_cache.py +++ b/pygccxml/parser/directory_cache.py @@ -540,7 +540,7 @@ def _get_signature(self, entry): # return file modification date... try: return os.path.getmtime(entry.filename) - except OSError as e: + except OSError: return None def _dump(self): diff --git a/pygccxml/parser/project_reader.py b/pygccxml/parser/project_reader.py index 1c429c90..9782bc11 100644 --- a/pygccxml/parser/project_reader.py +++ b/pygccxml/parser/project_reader.py @@ -477,7 +477,6 @@ def _join_class_hierarchy(self, namespaces): if id(leaved_classes[key]) == id(class_): continue else: - declarations = None if class_.parent: declarations = class_.parent.declarations else: diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index 580af9c5..b70cd889 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -515,7 +515,6 @@ def __read_variable(self, attrs): __read_field = __read_variable # just a synonim def __read_class_impl(self, class_type, attrs): - decl = None name = attrs.get(XML_AN_NAME, '') if '$' in name or '.' in name: name = '' diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 6928d4d1..2c038fe3 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -319,7 +319,7 @@ def create_xml_file_from_string(self, content, destination=None): :rtype: returns file name of GCC-XML generated file """ header_file = pygccxml.utils.create_temp_file_name(suffix='.h') - xml_file = None + try: header_file_obj = open(header_file, 'w+') header_file_obj.write(content) diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index 86477c6c..ce0f387a 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -46,7 +46,6 @@ def find_xml_generator(name=None): else: command = "which" - path = "" if name is None: name = "gccxml" p = subprocess.Popen([command, name], stdout=subprocess.PIPE) From cd11995f033e6fe65423a2cdecb7db5e7303345c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 7 Nov 2015 16:45:35 +0100 Subject: [PATCH 016/268] Start rewording and cleaning up design.rst --- docs/apidocs/utils.rst | 2 +- docs/design.rst | 41 ++++++++++++++++++++++++++--------------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/docs/apidocs/utils.rst b/docs/apidocs/utils.rst index 171ec220..2c3d6e16 100644 --- a/docs/apidocs/utils.rst +++ b/docs/apidocs/utils.rst @@ -2,7 +2,7 @@ pygccxml.utils package ====================== Modules --------- +------- .. automodule:: pygccxml.utils.utils :members: diff --git a/docs/design.rst b/docs/design.rst index 701072e2..c57ecbca 100644 --- a/docs/design.rst +++ b/docs/design.rst @@ -2,28 +2,31 @@ Design overview =============== ------------------------- -The view from 10000 fits ------------------------- - pygccxml has 4 packages: -* :mod:`declarations ` package defines classes that describe - C++ declarations and types +* :mod:`declarations ` + + This package defines classes that describe C++ declarations and types. + +* :mod:`parser ` + + This package defines classes that parse `GCC-XML`_ + or `CastXML`_ generated files. It also defines a few classes that will help + you unnecessary parsing of C++ source files. -* :mod:`parser ` package defines classes that parse `GCC-XML`_ - generated files. Also it defines few classes that will help you to eliminate - unnecessary parsing of C++ source files. +* :mod:`binary_parsers ` -* :mod:`binary_parsers ` package extracts some - information from binary files ( `.so`, `.dll`, `.map` ) and merges it with - the declarations tree. + This package extracts information from binary files (`.so`, `.dll`, `.map`) + and merges it with the declarations tree. -* ``utils`` package defines few functions, I found useful in the whole project. +* :mod:`utils ` -------------------------- + This package defines a few functions useful for the whole project, + but which are mainly used internally by pygccxml. + +------------------------ ``declarations`` package -------------------------- +------------------------ Please take a look on the `UML diagram`_. This `UML diagram`_ describes almost all classes defined in the package and their relationship. ``declarations`` package @@ -275,6 +278,13 @@ This is not the only bug, which could be fixed, there are few of them. pygccxml introduces few classes, which knows how to deal with specific bug. More over, those bugs are fixed, only if I am 101% sure, that this is the right thing to do. +----------------- +``utils`` package +----------------- + + Use internally by pygccxml. + Some methods/classes may be still usefull: loggers, find_xml_generator + ------- Summary ------- @@ -287,6 +297,7 @@ information please read API documentation. .. _`SourceForge`: http://sourceforge.net/index.php .. _`Python`: http://www.python.org .. _`GCC-XML`: http://www.gccxml.org +.. _`CastXML`: https://github.com/CastXML/CastXML .. _`UML diagram` : declarations_uml.png .. _`parser package UML diagram` : parser_uml.png .. _`ReleaseForge` : http://releaseforge.sourceforge.net From 73bfce745c6571c7c803767c3c5d7957bd7a9e7d Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 7 Nov 2015 22:19:01 +0100 Subject: [PATCH 017/268] Move location_t class to separate location.py file This class is big enough to live in it's own file --- pygccxml/declarations/__init__.py | 2 +- pygccxml/declarations/declaration.py | 63 -------------------------- pygccxml/declarations/location.py | 67 ++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 64 deletions(-) create mode 100644 pygccxml/declarations/location.py diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 3f248982..aaa73bf9 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -13,7 +13,7 @@ from . import xml_generators from .dependencies import dependency_info_t -from .declaration import location_t +from .location import location_t from .declaration import declaration_t from .scopedef import scopedef_t from .enumeration import enumeration_t diff --git a/pygccxml/declarations/declaration.py b/pygccxml/declarations/declaration.py index 6d028816..7a52beec 100644 --- a/pygccxml/declarations/declaration.py +++ b/pygccxml/declarations/declaration.py @@ -15,69 +15,6 @@ from .. import utils -class location_t(object): - """ - Provides information about the location of the declaration within the - source file. - - """ - - def __init__(self, file_name='', line=-1): - self._file_name = file_name - self._line = line - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return False - return self.line == other.line \ - and self.file_name == other.file_name - - def __hash__(self): - return hash(self.__class__) ^ hash(self.line) ^ hash(self.file_name) - - def __ne__(self, other): - return not self.__eq__(other) - - def __lt__(self, other): - if not isinstance(other, location_t): - return self.__class__.__name__ < other.__class__.__name__ - return (self.file_name, self.line) < (other.file_name, other.line) - - @property - def file_name(self): - """ - Absolute source file name, type string. - - """ - - return self._file_name - - @file_name.setter - def file_name(self, new_file_name): - self._file_name = new_file_name - - @property - def line(self): - """ - Line number, type int. - - """ - - return self._line - - @line.setter - def line(self, new_line): - self._line = new_line - - def as_tuple(self): - """ - Return tuple(self.file_name, self.line) - - """ - - return (self.file_name, self.line) - - class declaration_t(object): """ Base class for all classes that represent a C++ declaration. diff --git a/pygccxml/declarations/location.py b/pygccxml/declarations/location.py new file mode 100644 index 00000000..242c0a75 --- /dev/null +++ b/pygccxml/declarations/location.py @@ -0,0 +1,67 @@ +# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + + +class location_t(object): + """ + Provides information about the location of the declaration within the + source file. + + """ + + def __init__(self, file_name='', line=-1): + self._file_name = file_name + self._line = line + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return False + return self.line == other.line \ + and self.file_name == other.file_name + + def __hash__(self): + return hash(self.__class__) ^ hash(self.line) ^ hash(self.file_name) + + def __ne__(self, other): + return not self.__eq__(other) + + def __lt__(self, other): + if not isinstance(other, location_t): + return self.__class__.__name__ < other.__class__.__name__ + return (self.file_name, self.line) < (other.file_name, other.line) + + @property + def file_name(self): + """ + Absolute source file name, type string. + + """ + + return self._file_name + + @file_name.setter + def file_name(self, new_file_name): + self._file_name = new_file_name + + @property + def line(self): + """ + Line number, type int. + + """ + + return self._line + + @line.setter + def line(self, new_line): + self._line = new_line + + def as_tuple(self): + """ + Return tuple(self.file_name, self.line) + + """ + + return (self.file_name, self.line) From f9461e42f5e9a57025194e4c7c3a245529ae172f Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 9 Nov 2015 16:51:43 +0100 Subject: [PATCH 018/268] Remove unused methods --- pygccxml/parser/scanner.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index b70cd889..15fda47d 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -188,12 +188,6 @@ def access(self): def members(self): return self.__members - def startElementNS(self, name, qname, attrs): - return self.startElement(name[1], attrs) - - def endElementNS(self, name, qname): - return self.endElement(name[1]) - def startElement(self, name, attrs): try: From 819508ef51204a89b8b1e06b1fd5290ccaca6685 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 9 Nov 2015 17:01:02 +0100 Subject: [PATCH 019/268] Remove redundant parentheses --- pygccxml/declarations/decl_printer.py | 18 +++++++++--------- pygccxml/declarations/enumeration.py | 2 +- pygccxml/declarations/location.py | 2 +- pygccxml/declarations/pattern_parser.py | 2 +- pygccxml/parser/declarations_cache.py | 2 +- pygccxml/parser/directory_cache.py | 4 ++-- pygccxml/parser/project_reader.py | 4 ++-- pygccxml/parser/source_reader.py | 2 +- pygccxml/utils/utils.py | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/pygccxml/declarations/decl_printer.py b/pygccxml/declarations/decl_printer.py index 8b0c95b5..78f7fd8b 100644 --- a/pygccxml/declarations/decl_printer.py +++ b/pygccxml/declarations/decl_printer.py @@ -148,7 +148,7 @@ def print_decl_header(self): artificial.ljust( self.JUSTIFY)) if self.__inst.attributes: - attributes = 'attributes: %s' % (self.__inst.attributes) + attributes = 'attributes: %s' % self.__inst.attributes self.writer( ' ' * curr_level * @@ -157,7 +157,7 @@ def print_decl_header(self): if "GCC" in utils.xml_generator and self.__inst.demangled: # Working only with gccxml. # No demangled attribute with castxml - demangled = 'demangled: %s' % (self.__inst.demangled) + demangled = 'demangled: %s' % self.__inst.demangled self.writer( ' ' * curr_level * @@ -177,7 +177,7 @@ def print_decl_header(self): print_mangled = True if print_mangled: - mangled = 'mangled: %s' % (self.__inst.mangled) + mangled = 'mangled: %s' % self.__inst.mangled self.writer( ' ' * curr_level * @@ -279,7 +279,7 @@ def visit_class(self): class_type.ljust( self.JUSTIFY)) if self.__print_details: - byte_size = 'size: %d' % (self.__inst.byte_size) + byte_size = 'size: %d' % self.__inst.byte_size self.writer( ' ' * curr_level * @@ -287,7 +287,7 @@ def visit_class(self): byte_size.ljust( self.JUSTIFY)) try: - byte_align = 'align: %d' % (self.__inst.byte_align) + byte_align = 'align: %d' % self.__inst.byte_align self.writer( ' ' * curr_level * @@ -434,7 +434,7 @@ def visit_variable(self): self.__inst.value) if self.__print_details: if self.__inst.bits: - bits = 'bits: %d' % (self.__inst.bits) + bits = 'bits: %d' % self.__inst.bits self.writer( ' ' * curr_level * @@ -442,7 +442,7 @@ def visit_variable(self): bits.ljust( self.JUSTIFY)) - byte_size = 'size: %d' % (self.__inst.type.byte_size) + byte_size = 'size: %d' % self.__inst.type.byte_size self.writer( ' ' * curr_level * @@ -450,7 +450,7 @@ def visit_variable(self): byte_size.ljust( self.JUSTIFY)) try: - byte_align = 'align: %d' % (self.__inst.type.byte_align) + byte_align = 'align: %d' % self.__inst.type.byte_align self.writer( ' ' * curr_level * @@ -464,7 +464,7 @@ def visit_variable(self): self.INDENT_SIZE + "align: not implemented".ljust( self.JUSTIFY)) - byte_offset = 'offset: %d' % (self.__inst.byte_offset) + byte_offset = 'offset: %d' % self.__inst.byte_offset self.writer( ' ' * curr_level * diff --git a/pygccxml/declarations/enumeration.py b/pygccxml/declarations/enumeration.py index 2895df62..fab0ec94 100644 --- a/pygccxml/declarations/enumeration.py +++ b/pygccxml/declarations/enumeration.py @@ -64,7 +64,7 @@ def values(self): def values(self, values): self._values = [] # None is treated like an empty list - if (values is None): + if values is None: return # Check that we have indeed a list... if not isinstance(values, list): diff --git a/pygccxml/declarations/location.py b/pygccxml/declarations/location.py index 242c0a75..39a336c7 100644 --- a/pygccxml/declarations/location.py +++ b/pygccxml/declarations/location.py @@ -64,4 +64,4 @@ def as_tuple(self): """ - return (self.file_name, self.line) + return self.file_name, self.line diff --git a/pygccxml/declarations/pattern_parser.py b/pygccxml/declarations/pattern_parser.py index 7e75be6f..2321d023 100644 --- a/pygccxml/declarations/pattern_parser.py +++ b/pygccxml/declarations/pattern_parser.py @@ -102,7 +102,7 @@ def find_args(self, text, start=None): if -1 == found: return self.NOT_FOUND elif text[found] == self.__end: - return (first_occurance, found) + return first_occurance, found else: previous_found = found + 1 # skip found sep diff --git a/pygccxml/parser/declarations_cache.py b/pygccxml/parser/declarations_cache.py index 6b54ffe1..55148591 100644 --- a/pygccxml/parser/declarations_cache.py +++ b/pygccxml/parser/declarations_cache.py @@ -115,7 +115,7 @@ def was_hit(self, was_hit): self.__was_hit = was_hit def key(self): - return (self.__source_signature, self.__config_signature) + return self.__source_signature, self.__config_signature @staticmethod def create_key(source_file, configuration): diff --git a/pygccxml/parser/directory_cache.py b/pygccxml/parser/directory_cache.py index dd7098d4..0105d4f3 100644 --- a/pygccxml/parser/directory_cache.py +++ b/pygccxml/parser/directory_cache.py @@ -49,7 +49,7 @@ def __init__(self, filesigs, configsig): self.configsig = configsig def __getstate__(self): - return (self.filesigs, self.configsig) + return self.filesigs, self.configsig def __setstate__(self, state): self.filesigs, self.configsig = state @@ -404,7 +404,7 @@ def __init__(self, filename): def __getstate__(self): # Only pickle filename and refcount - return (self.filename, self.refcount) + return self.filename, self.refcount def __setstate__(self, state): self.filename, self.refcount = state diff --git a/pygccxml/parser/project_reader.py b/pygccxml/parser/project_reader.py index 9782bc11..6e619c85 100644 --- a/pygccxml/parser/project_reader.py +++ b/pygccxml/parser/project_reader.py @@ -497,9 +497,9 @@ def _create_name_key(self, decl): # Not all declarations have a mangled name with castxml # we can only rely on the name if "GCC" in utils.xml_generator: - return (decl.location.as_tuple(), decl.mangled) + return decl.location.as_tuple(), decl.mangled elif "CastXML" in utils.xml_generator: - return (decl.location.as_tuple(), decl.name) + return decl.location.as_tuple(), decl.name def _relink_declarated_types(self, leaved_classes, declarated_types): diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 2c038fe3..508bb6bc 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -478,7 +478,7 @@ def __parse_xml_file(self, xml_file): decls.values()) if isinstance( inst, declarations.namespace_t) and not inst.parent] - return (decls, list(files.values())) + return decls, list(files.values()) def join_declarations(self, declref): self._join_namespaces(declref) diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index ce0f387a..469d0878 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -313,7 +313,7 @@ def get_version(): return None # not implemented yet else: from distutils import msvccompiler - return ('msvc', str(msvccompiler.get_build_version())) + return 'msvc', str(msvccompiler.get_build_version()) @staticmethod def get_gccxml_compiler(): From c1508c9881ed9d36c3e27d262f905770b3e1096c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 9 Nov 2015 17:03:37 +0100 Subject: [PATCH 020/268] Use the variable() method instead of var() in the tests (var() was deprecated) --- unittests/array_bug_tester.py | 8 ++++---- unittests/core_tester.py | 2 +- unittests/gccxml10184_tester.py | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/unittests/array_bug_tester.py b/unittests/array_bug_tester.py index 870f7018..6180321b 100644 --- a/unittests/array_bug_tester.py +++ b/unittests/array_bug_tester.py @@ -20,7 +20,7 @@ def test1(self): src_reader = parser.source_reader_t(self.config) global_ns = declarations.get_global_namespace( src_reader.read_string(code)) - aaaa_type = global_ns.var('aaaa').type + aaaa_type = global_ns.variable('aaaa').type self.failUnless( 'int[2][3][4][5]' == aaaa_type.decl_string, aaaa_type.decl_string) @@ -30,7 +30,7 @@ def test2(self): src_reader = parser.source_reader_t(self.config) global_ns = declarations.get_global_namespace( src_reader.read_string(code)) - aaaa_type = global_ns.var('aaaa').type + aaaa_type = global_ns.variable('aaaa').type self.failUnless( 'int *[2][3][4][5]' == aaaa_type.decl_string, aaaa_type.decl_string) @@ -40,7 +40,7 @@ def test3(self): src_reader = parser.source_reader_t(self.config) global_ns = declarations.get_global_namespace( src_reader.read_string(code)) - aaaa_type = global_ns.var('aaaa').type + aaaa_type = global_ns.variable('aaaa').type self.failUnless( 'int[2]' == aaaa_type.decl_string, aaaa_type.decl_string) @@ -50,7 +50,7 @@ def test4(self): src_reader = parser.source_reader_t(self.config) global_ns = declarations.get_global_namespace( src_reader.read_string(code)) - aaaa_type = global_ns.var('aaaa').type + aaaa_type = global_ns.variable('aaaa').type self.failUnless( '::xyz[2][3]' == aaaa_type.decl_string, aaaa_type.decl_string) diff --git a/unittests/core_tester.py b/unittests/core_tester.py index 71256ed3..ff33439c 100644 --- a/unittests/core_tester.py +++ b/unittests/core_tester.py @@ -558,7 +558,7 @@ def test_byte_align(self): def test_byte_offset(self): mptrs = self.global_ns.class_('members_pointers_t') - self.failUnless(mptrs.var('xxx').byte_offset != 0) + self.failUnless(mptrs.variable('xxx').byte_offset != 0) class core_gccxml_t(core_t): diff --git a/unittests/gccxml10184_tester.py b/unittests/gccxml10184_tester.py index 0705c669..c53ef13b 100644 --- a/unittests/gccxml10184_tester.py +++ b/unittests/gccxml10184_tester.py @@ -28,8 +28,8 @@ def test(self): src_reader = parser.source_reader_t(self.config) global_ns = declarations.get_global_namespace( src_reader.read_string(code)) - self.failUnless(global_ns.var('a').bits == 1) - self.failUnless(global_ns.var('unused').bits == 31) + self.failUnless(global_ns.variable('a').bits == 1) + self.failUnless(global_ns.variable('unused').bits == 31) def create_suite(): From 839f94a4468de52cc6cf64480bd6a1627619da4c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 9 Nov 2015 20:25:18 +0100 Subject: [PATCH 021/268] Do not check twice for arg.default_value, this is already done in the loop (see __call__ method) --- pygccxml/parser/patcher.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pygccxml/parser/patcher.py b/pygccxml/parser/patcher.py index 8decdb20..87ada735 100644 --- a/pygccxml/parser/patcher.py +++ b/pygccxml/parser/patcher.py @@ -22,9 +22,7 @@ def __call__(self, decl): arg.default_value = fixer(decl, arg) def __find_fixer(self, func, arg): - if not arg.default_value: - return False - elif self.__is_unqualified_enum(func, arg): + if self.__is_unqualified_enum(func, arg): return self.__fix_unqualified_enum elif self.__is_double_call(func, arg): return self.__fix_double_call From c3277345a9d9c35cc65b607a80e10d01aff316f5 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 Nov 2015 21:41:53 +0100 Subject: [PATCH 022/268] Use shall instead of md5 Performance is not affected here. This is needed to make the quantifiedcode linter happy. As there is not much difference between the two, sha1 seems OK and can be used instead. --- pygccxml/parser/declarations_cache.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pygccxml/parser/declarations_cache.py b/pygccxml/parser/declarations_cache.py index 55148591..0de36ef6 100644 --- a/pygccxml/parser/declarations_cache.py +++ b/pygccxml/parser/declarations_cache.py @@ -22,7 +22,7 @@ def file_signature(filename): # Extend here to use md5 hash for signature # - This change allows duplicate auto-generated files to be recognized - sig = hashlib.md5() + sig = hashlib.sha1() with open(filename, "rb") as f: buf = f.read() sig.update(buf) @@ -38,7 +38,7 @@ def configuration_signature(config): to be different between runs. """ - sig = hashlib.md5() + sig = hashlib.sha1() if isinstance(config, cxx_parsers_cfg.xml_generator_configuration_t): sig.update(str(config.xml_generator_path).encode()) sig.update(str(config.working_directory).encode('utf-8')) From b6969e30eba808aae04bcce283aaa2eaf975b4fa Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 Nov 2015 21:48:51 +0100 Subject: [PATCH 023/268] Update docstrings --- pygccxml/parser/declarations_cache.py | 37 +++++++++++++++++---------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/pygccxml/parser/declarations_cache.py b/pygccxml/parser/declarations_cache.py index 0de36ef6..9fe5e911 100644 --- a/pygccxml/parser/declarations_cache.py +++ b/pygccxml/parser/declarations_cache.py @@ -15,13 +15,17 @@ def file_signature(filename): + """ + Return a signature for a file. + + """ + if not os.path.isfile(filename): return None if not os.path.exists(filename): return None - # Extend here to use md5 hash for signature - # - This change allows duplicate auto-generated files to be recognized + # Duplicate auto-generated files can be recognized with the sha1 hash. sig = hashlib.sha1() with open(filename, "rb") as f: buf = f.read() @@ -31,11 +35,15 @@ def file_signature(filename): def configuration_signature(config): - """ Return a signature for a configuration (xml_generator_configuration_t) - object. This can then be used as a key in the cache. - This method must take into account anything about - a configuration that could cause the declarations generated - to be different between runs. + """ + Return a signature for a configuration (xml_generator_configuration_t) + object. + + This can then be used as a key in the cache. + This method must take into account anything about + a configuration that could cause the declarations generated + to be different between runs. + """ sig = hashlib.sha1() @@ -241,7 +249,9 @@ def cached_value(self, source_file, configuration): """ Attempt to lookup the cached declarations for the given file and configuration. - If not found or signature check fails, returns None. + + Returns None if declaration not found or signature check fails. + """ key = record_t.create_key(source_file, configuration) @@ -249,17 +259,13 @@ def cached_value(self, source_file, configuration): return None record = self.__cache[key] if self.__is_valid_signature(record): - record.was_hit = True # Record cache hit + record.was_hit = True # Record cache hit return record.declarations else: # some file has been changed del self.__cache[key] return None def __is_valid_signature(self, record): - # This is now part of key - # if self.__signature( record.source_file ) != \ - # record.source_file_signature: - # return False for index, included_file in enumerate(record.included_files): if file_signature(included_file) != \ record.included_files_signature[index]: @@ -269,6 +275,11 @@ def __is_valid_signature(self, record): class dummy_cache_t(cache_base_t): + """ + By default no caching is enabled in pygccxml. This is an empty cache object. + + """ + def __init__(self): cache_base_t.__init__(self) From f834a2cf1451005b9dfbbf04177db3ec5f18770d Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 Nov 2015 22:35:59 +0100 Subject: [PATCH 024/268] Fix line too long --- pygccxml/parser/declarations_cache.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pygccxml/parser/declarations_cache.py b/pygccxml/parser/declarations_cache.py index 9fe5e911..6421cede 100644 --- a/pygccxml/parser/declarations_cache.py +++ b/pygccxml/parser/declarations_cache.py @@ -276,7 +276,9 @@ def __is_valid_signature(self, record): class dummy_cache_t(cache_base_t): """ - By default no caching is enabled in pygccxml. This is an empty cache object. + This is an empty cache object. + + By default no caching is enabled in pygccxml. """ From 3af7e1c58a4858b20d4aa70962e6c0183a723c39 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 Nov 2015 22:59:34 +0100 Subject: [PATCH 025/268] Also use sha1 in directory cache --- pygccxml/parser/directory_cache.py | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/pygccxml/parser/directory_cache.py b/pygccxml/parser/directory_cache.py index 0105d4f3..1924f9cb 100644 --- a/pygccxml/parser/directory_cache.py +++ b/pygccxml/parser/directory_cache.py @@ -68,15 +68,15 @@ class directory_cache_t (declarations_cache.cache_base_t): modified since the last run). """ - def __init__(self, dir="cache", compression=False, md5_sigs=True): + def __init__(self, dir="cache", compression=False, sha1_sigs=True): """ :param dir: cache directory path, it is created, if it does not exist :param compression: if `True`, the cache files will be compressed using `gzip` - :param md5_sigs: `md5_sigs` determines whether file modifications is - checked by computing a `md5` digest or by checking + :param sha1_sigs: `sha1_sigs` determines whether file modifications is + checked by computing a `sha1` digest or by checking the modification date """ @@ -88,13 +88,13 @@ def __init__(self, dir="cache", compression=False, md5_sigs=True): # Flag that determines whether the cache files will be compressed self.__compression = compression - # Flag that determines whether the signature is a md5 digest or + # Flag that determines whether the signature is a sha1 digest or # the modification time # (this flag is passed to the filename_repository_t class) - self.__md5_sigs = md5_sigs + self.__sha1_sigs = sha1_sigs # Filename repository - self.__filename_rep = filename_repository_t(self.__md5_sigs) + self.__filename_rep = filename_repository_t(self.__sha1_sigs) # Index dictionary (Key is the value returned by _create_cache_key() # (which is based on the header file name) and value is an @@ -228,15 +228,15 @@ def _load(self): data = self._read_file(indexfilename) self.__index = data[0] self.__filename_rep = data[1] - if self.__filename_rep._md5_sigs != self.__md5_sigs: + if self.__filename_rep._sha1_sigs != self.__sha1_sigs: print(( - "CACHE: Warning: md5_sigs stored in the cache is set " + - "to %s.") % self.__filename_rep._md5_sigs) + "CACHE: Warning: sha1_sigs stored in the cache is set " + + "to %s.") % self.__filename_rep._sha1_sigs) print("Please remove the cache to change this setting.") - self.__md5_sigs = self.__filename_rep._md5_sigs + self.__sha1_sigs = self.__filename_rep._sha1_sigs else: self.__index = {} - self.__filename_rep = filename_repository_t(self.__md5_sigs) + self.__filename_rep = filename_repository_t(self.__sha1_sigs) self.__modified_flag = False @@ -355,7 +355,7 @@ def _create_config_signature(self, config): """ return the signature for a config object. - The signature is computed as md5 digest of the contents of + The signature is computed as sha1 digest of the contents of working_directory, include_paths, define_symbols and undefine_symbols. @@ -363,7 +363,7 @@ def _create_config_signature(self, config): :type config: :class:`parser.xml_generator_configuration_t` :rtype: str """ - m = hashlib.md5() + m = hashlib.sha1() m.update(config.working_directory) for p in config.include_paths: m.update(p) @@ -436,14 +436,14 @@ class filename_repository_t: called so that the entry can be removed from the repository. """ - def __init__(self, md5_sigs): + def __init__(self, sha1_sigs): """Constructor. """ - # Flag that determines whether the signature is a md5 digest or + # Flag that determines whether the signature is a sha1 digest or # the modification time # (this flag is passed to the filename_repository_t class) - self._md5_sigs = md5_sigs + self._sha1_sigs = sha1_sigs # ID lookup table (key: filename / value: id_) self.__id_lut = {} @@ -524,18 +524,18 @@ def _get_signature(self, entry): """Return the signature of the file stored in entry. """ - if self._md5_sigs: - # return md5 digest of the file content... + if self._sha1_sigs: + # return sha1 digest of the file content... if not os.path.exists(entry.filename): return None try: f = open(entry.filename) except IOError as e: - print("Cannot determine md5 digest:", e) + print("Cannot determine sha1 digest:", e) return None data = f.read() f.close() - return hashlib.md5(data).digest() + return hashlib.sha1(data).digest() else: # return file modification date... try: From cb896e8f8e73b520e2e9574af0c1243d7fd9ca22 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 Nov 2015 23:08:16 +0100 Subject: [PATCH 026/268] Remove b mode from files This does not work well with python 3. Besides, most of these files are just there for unit tests, so this is not so important --- pygccxml/declarations/decl_printer.py | 2 +- unittests/file_cache_tester.py | 2 +- unittests/project_reader_correctness_tester.py | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pygccxml/declarations/decl_printer.py b/pygccxml/declarations/decl_printer.py index 78f7fd8b..40ca7fad 100644 --- a/pygccxml/declarations/decl_printer.py +++ b/pygccxml/declarations/decl_printer.py @@ -504,5 +504,5 @@ def dump_declarations(declarations, file_path): """ - with open(file_path, "wb+") as f: + with open(file_path, "w+") as f: print_declarations(declarations, writer=f.write) diff --git a/unittests/file_cache_tester.py b/unittests/file_cache_tester.py index 72ed9847..c108032e 100644 --- a/unittests/file_cache_tester.py +++ b/unittests/file_cache_tester.py @@ -53,7 +53,7 @@ def test_update(self): # We wrote a //touch in the header file. Just replace the file with the # original content. The touched file would be sometimes commited by # error as it was modified. - with open(self.header, "wb") as new_header: + with open(self.header, "w") as new_header: new_header.write(content) def test_from_file(self): diff --git a/unittests/project_reader_correctness_tester.py b/unittests/project_reader_correctness_tester.py index 87f83a40..056da067 100644 --- a/unittests/project_reader_correctness_tester.py +++ b/unittests/project_reader_correctness_tester.py @@ -41,10 +41,9 @@ def __test_correctness_impl(self, file_name): s = src_decls[0] p = prj_decls[0] bdir = autoconfig.build_directory - with open(os.path.join(bdir, file_name + '.sr.txt'), 'wb+') as sr: + with open(os.path.join(bdir, file_name + '.sr.txt'), 'w+') as sr: with open( - os.path.join(bdir, file_name + '.pr.txt'), - 'wb+') as pr: + os.path.join(bdir, file_name + '.pr.txt'), 'w+') as pr: declarations.print_declarations( s, writer=lambda l: sr.write(l + os.linesep)) From a7dd39925c467a805488a61f5a048e6111ef467b Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 Nov 2015 23:17:46 +0100 Subject: [PATCH 027/268] Use assertTrue instead of failUnless failUnless is deprecated since a long time now: https://docs.python.org/2/library/unittest.html#deprecated-aliases As Deprecation warnings are enabled in pygccxml; this clutters the test logs --- unittests/algorithms_cache_tester.py | 30 +++---- unittests/array_bug_tester.py | 8 +- unittests/attributes_tester.py | 6 +- unittests/bit_fields_tester.py | 6 +- unittests/cache_enums_tester.py | 2 +- unittests/cached_source_file_tester.py | 4 +- unittests/call_invocation_tester.py | 16 ++-- unittests/calldef_matcher_tester.py | 2 +- unittests/calling_convention_tester.py | 2 +- unittests/const_volatile_arg_tester.py | 8 +- unittests/copy_constructor_tester.py | 6 +- unittests/core_tester.py | 82 +++++++++---------- unittests/decl_string_tester.py | 8 +- unittests/declaration_files_tester.py | 2 +- unittests/declaration_matcher_tester.py | 4 +- unittests/declarations_comparison_tester.py | 8 +- unittests/declarations_tester.py | 56 ++++++------- unittests/demangled_tester.py | 10 +-- unittests/dependencies_tester.py | 36 ++++---- unittests/file_cache_tester.py | 8 +- unittests/filters_tester.py | 18 ++-- unittests/find_container_traits_tester.py | 28 +++---- unittests/free_operators_tester.py | 4 +- unittests/function_traits_tester.py | 2 +- unittests/gccxml10183_tester.py | 2 +- unittests/gccxml10184_tester.py | 4 +- unittests/gccxml_runner_tester.py | 2 +- .../has_binary_operator_traits_tester.py | 4 +- unittests/hierarchy_traveling.py | 12 +-- unittests/inline_specifier_tester.py | 8 +- unittests/namespace_matcher_tester.py | 4 +- unittests/parser_test_case.py | 16 ++-- unittests/patcher_tester.py | 32 ++++---- unittests/plain_c_tester.py | 2 +- .../project_reader_correctness_tester.py | 2 +- unittests/remove_template_defaults_tester.py | 60 +++++++------- unittests/source_reader_tester.py | 2 +- unittests/start_with_declarations_tester.py | 8 +- unittests/string_traits_tester.py | 4 +- unittests/templates_tester.py | 12 +-- unittests/test_create_decl_string.py | 4 +- unittests/text_reader_tester.py | 2 +- unittests/type_as_exception_bug_tester.py | 6 +- unittests/type_traits_tester.py | 76 ++++++++--------- unittests/typedefs_tester.py | 12 +-- unittests/undname_creator_tester.py | 12 +-- unittests/unnamed_classes_tester.py | 2 +- unittests/unnamed_enums_bug_tester.py | 34 ++++---- unittests/variable_matcher_tester.py | 6 +- unittests/vector_traits_tester.py | 10 +-- 50 files changed, 347 insertions(+), 347 deletions(-) diff --git a/unittests/algorithms_cache_tester.py b/unittests/algorithms_cache_tester.py index ccaef8d8..d37af347 100644 --- a/unittests/algorithms_cache_tester.py +++ b/unittests/algorithms_cache_tester.py @@ -29,42 +29,42 @@ def test_name_based(self): if "CastXML" in utils.xml_generator: self.assertRaises(Exception, lambda: cls.cache.demangled_name) elif "GCCXML" in utils.xml_generator: - self.failUnless(cls.cache.demangled_name == cls.name) + self.assertTrue(cls.cache.demangled_name == cls.name) cls_full_name = declarations.full_name(cls) - self.failUnless(cls.cache.full_name == cls_full_name) + self.assertTrue(cls.cache.full_name == cls_full_name) cls_declaration_path = declarations.declaration_path(cls) - self.failUnless(cls.cache.declaration_path == cls_declaration_path) + self.assertTrue(cls.cache.declaration_path == cls_declaration_path) enum = cls.enum('ENestedPublic') enum_full_name = declarations.full_name(enum) - self.failUnless(enum.cache.full_name == enum_full_name) + self.assertTrue(enum.cache.full_name == enum_full_name) enum_declaration_path = declarations.declaration_path(enum) - self.failUnless(enum.cache.declaration_path == enum_declaration_path) + self.assertTrue(enum.cache.declaration_path == enum_declaration_path) # now we change class name, all internal decls cache should be cleared cls.name = "new_name" - self.failUnless(not cls.cache.full_name) + self.assertTrue(not cls.cache.full_name) if "GCCXML" in utils.xml_generator: - self.failUnless(not cls.cache.demangled_name) - self.failUnless(not cls.cache.declaration_path) + self.assertTrue(not cls.cache.demangled_name) + self.assertTrue(not cls.cache.declaration_path) - self.failUnless(not enum.cache.full_name) + self.assertTrue(not enum.cache.full_name) if "GCCXML" in utils.xml_generator: - self.failUnless(not enum.cache.demangled_name) - self.failUnless(not enum.cache.declaration_path) + self.assertTrue(not enum.cache.demangled_name) + self.assertTrue(not enum.cache.declaration_path) def test_access_type(self): cls = self.global_ns.class_(name='class_for_nested_enums_t') enum = cls.enum('ENestedPublic') - self.failUnless(enum.cache.access_type == 'public') + self.assertTrue(enum.cache.access_type == 'public') enum.cache.reset_access_type() - self.failUnless(not enum.cache.access_type) - self.failUnless('public' == cls.find_out_member_access_type(enum)) - self.failUnless(enum.cache.access_type == 'public') + self.assertTrue(not enum.cache.access_type) + self.assertTrue('public' == cls.find_out_member_access_type(enum)) + self.assertTrue(enum.cache.access_type == 'public') def create_suite(): diff --git a/unittests/array_bug_tester.py b/unittests/array_bug_tester.py index 6180321b..9ee183d1 100644 --- a/unittests/array_bug_tester.py +++ b/unittests/array_bug_tester.py @@ -21,7 +21,7 @@ def test1(self): global_ns = declarations.get_global_namespace( src_reader.read_string(code)) aaaa_type = global_ns.variable('aaaa').type - self.failUnless( + self.assertTrue( 'int[2][3][4][5]' == aaaa_type.decl_string, aaaa_type.decl_string) @@ -31,7 +31,7 @@ def test2(self): global_ns = declarations.get_global_namespace( src_reader.read_string(code)) aaaa_type = global_ns.variable('aaaa').type - self.failUnless( + self.assertTrue( 'int *[2][3][4][5]' == aaaa_type.decl_string, aaaa_type.decl_string) @@ -41,7 +41,7 @@ def test3(self): global_ns = declarations.get_global_namespace( src_reader.read_string(code)) aaaa_type = global_ns.variable('aaaa').type - self.failUnless( + self.assertTrue( 'int[2]' == aaaa_type.decl_string, aaaa_type.decl_string) @@ -51,7 +51,7 @@ def test4(self): global_ns = declarations.get_global_namespace( src_reader.read_string(code)) aaaa_type = global_ns.variable('aaaa').type - self.failUnless( + self.assertTrue( '::xyz[2][3]' == aaaa_type.decl_string, aaaa_type.decl_string) diff --git a/unittests/attributes_tester.py b/unittests/attributes_tester.py index 96bf749b..798aec2f 100644 --- a/unittests/attributes_tester.py +++ b/unittests/attributes_tester.py @@ -38,12 +38,12 @@ def test(self): # always on ubuntu (clang and gcc). Just skip this test for the # moment. - # self.failUnless(None is numeric.attributes) + # self.assertTrue(None is numeric.attributes) do_nothing = numeric.mem_fun('do_nothing') - self.failUnless((prefix + "(no throw)") == do_nothing.attributes) + self.assertTrue((prefix + "(no throw)") == do_nothing.attributes) arg = do_nothing.arguments[0] - self.failUnless((prefix + "(out)") == arg.attributes) + self.assertTrue((prefix + "(out)") == arg.attributes) def create_suite(): diff --git a/unittests/bit_fields_tester.py b/unittests/bit_fields_tester.py index abf7168c..f53d2921 100644 --- a/unittests/bit_fields_tester.py +++ b/unittests/bit_fields_tester.py @@ -26,13 +26,13 @@ def setUp(self): def test(self): bf_x = self.global_ns.variable('x') - self.failUnless(bf_x.bits == 1) + self.assertTrue(bf_x.bits == 1) bf_y = self.global_ns.variable('y') - self.failUnless(bf_y.bits == 7) + self.assertTrue(bf_y.bits == 7) mv_z = self.global_ns.variable('z') - self.failUnless(mv_z.bits is None) + self.assertTrue(mv_z.bits is None) def test2(self): pass diff --git a/unittests/cache_enums_tester.py b/unittests/cache_enums_tester.py index ac45944e..69f87cd6 100644 --- a/unittests/cache_enums_tester.py +++ b/unittests/cache_enums_tester.py @@ -40,7 +40,7 @@ def test_cache(self): color1 = declarations.matcher.get_single(enum_matcher, decls1) color2 = declarations.matcher.get_single(enum_matcher, decls2) - self.failUnless(color1.values == color2.values) + self.assertTrue(color1.values == color2.values) # there is no progress with this parser # class synopsis_tester_t( tester_impl_t ): diff --git a/unittests/cached_source_file_tester.py b/unittests/cached_source_file_tester.py index 6e1d4e1f..a87f5009 100644 --- a/unittests/cached_source_file_tester.py +++ b/unittests/cached_source_file_tester.py @@ -27,13 +27,13 @@ def test(self): prj_reader.read_files( [fconfig], compilation_mode=parser.COMPILATION_MODE.FILE_BY_FILE) - self.failUnless(os.path.exists(fconfig.cached_source_file)) + self.assertTrue(os.path.exists(fconfig.cached_source_file)) mtime1 = os.stat(fconfig.cached_source_file)[stat.ST_MTIME] prj_reader.read_files( [fconfig], compilation_mode=parser.COMPILATION_MODE.FILE_BY_FILE) mtime2 = os.stat(fconfig.cached_source_file)[stat.ST_MTIME] - self.failUnless(mtime1 == mtime2) + self.assertTrue(mtime1 == mtime2) finally: utils.remove_file_no_raise(fconfig.cached_source_file, self.config) diff --git a/unittests/call_invocation_tester.py b/unittests/call_invocation_tester.py index ed9e310c..be8f72e4 100644 --- a/unittests/call_invocation_tester.py +++ b/unittests/call_invocation_tester.py @@ -13,16 +13,16 @@ def __init__(self, *args): unittest.TestCase.__init__(self, *args) def __test_split_impl(self, decl_string, name, args): - self.failUnless( + self.assertTrue( (name, args) == declarations.call_invocation.split(decl_string)) def __test_split_recursive_impl(self, decl_string, control_seq): - self.failUnless( + self.assertTrue( control_seq == declarations.call_invocation.split_recursive(decl_string)) def __test_is_call_invocation_impl(self, decl_string): - self.failUnless( + self.assertTrue( declarations.call_invocation.is_call_invocation(decl_string)) def test_split_on_vector(self): @@ -64,7 +64,7 @@ def test_split_on_map(self): " std::vector(int, std::allocator(int) ) ) )"]) def test_join_on_vector(self): - self.failUnless( + self.assertTrue( "vector( int, std::allocator(int) )" == declarations.call_invocation.join( "vector", ("int", "std::allocator(int)"))) @@ -72,14 +72,14 @@ def test_join_on_vector(self): def test_find_args(self): temp = 'x()()' found = declarations.call_invocation.find_args(temp) - self.failUnless((1, 2) == found) + self.assertTrue((1, 2) == found) found = declarations.call_invocation.find_args(temp, found[1] + 1) - self.failUnless((3, 4) == found) + self.assertTrue((3, 4) == found) temp = 'x(int,int)(1,2)' found = declarations.call_invocation.find_args(temp) - self.failUnless((1, 9) == found) + self.assertTrue((1, 9) == found) found = declarations.call_invocation.find_args(temp, found[1] + 1) - self.failUnless((10, 14) == found) + self.assertTrue((10, 14) == found) def test_bug_unmatched_brace(self): src = 'AlternativeName((&string("")), (&string("")), (&string("")))' diff --git a/unittests/calldef_matcher_tester.py b/unittests/calldef_matcher_tester.py index 782a5290..400389b2 100644 --- a/unittests/calldef_matcher_tester.py +++ b/unittests/calldef_matcher_tester.py @@ -27,7 +27,7 @@ def test(self): return_type='int', arg_types=[None, declarations.bool_t()]) rda = declarations.matcher.get_single(criteria, self.declarations) - self.failUnless(rda, "return_default_args function was not found.") + self.assertTrue(rda, "return_default_args function was not found.") def create_suite(): diff --git a/unittests/calling_convention_tester.py b/unittests/calling_convention_tester.py index 863b355e..b7759d6b 100644 --- a/unittests/calling_convention_tester.py +++ b/unittests/calling_convention_tester.py @@ -22,7 +22,7 @@ def test_extract(self): for expected, text in data: got = declarations.CALLING_CONVENTION_TYPES.extract(text) - self.failUnless( + self.assertTrue( got == expected, "Expected calling convention: %s, got %s" % (expected, got)) diff --git a/unittests/const_volatile_arg_tester.py b/unittests/const_volatile_arg_tester.py index 924c2777..5264a831 100644 --- a/unittests/const_volatile_arg_tester.py +++ b/unittests/const_volatile_arg_tester.py @@ -27,10 +27,10 @@ def setUp(self): def test(self): f = self.global_ns.free_fun('pygccxml_bug') t = f.arguments[0].type - self.failUnless(isinstance(t, declarations.pointer_t)) - self.failUnless(isinstance(t.base, declarations.volatile_t)) - self.failUnless(isinstance(t.base.base, declarations.const_t)) - self.failUnless(declarations.is_integral(t.base.base.base)) + self.assertTrue(isinstance(t, declarations.pointer_t)) + self.assertTrue(isinstance(t.base, declarations.volatile_t)) + self.assertTrue(isinstance(t.base.base, declarations.const_t)) + self.assertTrue(declarations.is_integral(t.base.base.base)) def create_suite(): diff --git a/unittests/copy_constructor_tester.py b/unittests/copy_constructor_tester.py index d41d0ac4..ebfb0f10 100644 --- a/unittests/copy_constructor_tester.py +++ b/unittests/copy_constructor_tester.py @@ -48,13 +48,13 @@ def tearDown(self): def test(self): for x in self.global_ns.typedefs('SettingsMultiMap'): - self.failUnless(not declarations.is_noncopyable(x)) + self.assertTrue(not declarations.is_noncopyable(x)) for x in self.global_ns.typedefs('SettingsIterator'): - self.failUnless(not declarations.is_noncopyable(x)) + self.assertTrue(not declarations.is_noncopyable(x)) for x in self.global_ns.typedefs('SectionIterator'): - self.failUnless(not declarations.is_noncopyable(x)) + self.assertTrue(not declarations.is_noncopyable(x)) def create_suite(): diff --git a/unittests/core_tester.py b/unittests/core_tester.py index ff33439c..4fe30cee 100644 --- a/unittests/core_tester.py +++ b/unittests/core_tester.py @@ -36,7 +36,7 @@ def __init__(self, *args): def test_top_parent(self): enum = self.global_ns.enum('::ns::ns32::E33') - self.failUnless(self.global_ns is enum.top_parent) + self.assertTrue(self.global_ns is enum.top_parent) # tests namespaces join functionality. described in gccxml.py def test_nss_join(self): @@ -66,7 +66,7 @@ def test_nss_join(self): ns12 = self.global_ns.namespace(nss[1]) ns22 = self.global_ns.namespace(nss[2]) ns32 = self.global_ns.namespace(nss[3]) - self.failUnless( + self.assertTrue( ns and ( ns is ns12.parent is ns22.parent is ns32.parent), 'There are 2 or more instances of ns namespace.') @@ -74,14 +74,14 @@ def test_nss_join(self): E11 = self.global_ns.enum(enums[0]) E21 = self.global_ns.enum(enums[1]) E31 = self.global_ns.enum(enums[2]) - self.failUnless( + self.assertTrue( E11.parent is E21.parent is E31.parent, 'There are 2 or more instances of global namespace.') nsE12 = self.global_ns.enum(enums[3]) nsE23 = self.global_ns.enum(enums[4]) nsE33 = self.global_ns.enum(enums[5]) - self.failUnless( + self.assertTrue( ns and ( ns is nsE12.parent is nsE23.parent is nsE33.parent), 'There are 2 or more instances of ns namespace.') @@ -92,24 +92,24 @@ def _test_ns_membership(self, ns, enum_name): autoconfig.data_directory, d.location.file_name), recursive=False) - self.failUnless( + self.assertTrue( unnamed_enum in ns.declarations, "namespace '%s' does not contains unnamed enum." % ns.name) enum = ns.enum(enum_name, recursive=False) - self.failUnless( + self.assertTrue( enum in ns.declarations, "namespace '%s' does not contains enum '%s'" % (ns.name, enum.name)) - self.failUnless( + self.assertTrue( unnamed_enum.parent is ns, ("unnamed enum belong to namespace '%s' but this namespace " + "is not it's parent.") % ns.name) - self.failUnless( + self.assertTrue( enum.parent is ns, ("enum '%s' belong to namespace '%s' but this namespace" + " is not it's parent.") % (enum.name, ns.name)) @@ -124,7 +124,7 @@ def _test_class_membership(self, class_inst, enum_name, access): nested_enum2 = class_inst.enum(enum_name) # it shoud be same object - self.failUnless( + self.assertTrue( nested_enum1 is nested_enum2, ("enum accessed through access definition('%s') and " + "through declarations('%s') are different enums " + @@ -132,7 +132,7 @@ def _test_class_membership(self, class_inst, enum_name, access): (nested_enum1.name, nested_enum2.name)) # check whether we meaning same class instance - self.failUnless( + self.assertTrue( class_inst is nested_enum1.parent is nested_enum2.parent, 'There are 2 or more instances of ns namespace.') @@ -173,11 +173,11 @@ def test_compiler_retrocompatibility(self): def test_mangled_name_namespace(self): std = self.global_ns.namespace("std") - self.failUnless(std, "std namespace has not been found") + self.assertTrue(std, "std namespace has not been found") # GCCXML had mangled names for everything. With CastXML # there are only mangled names for functions and variables. if "GCC" in utils.xml_generator: - self.failUnless( + self.assertTrue( std.mangled, "Mangled name of std namespace should be different from None") elif "CastXML" in utils.xml_generator: @@ -190,7 +190,7 @@ def test_mangled_name_functions(self): # This works with gccxml and castxml ns = self.global_ns.namespace("overloads") do_nothing = ns.calldefs("do_nothing", recursive=False) - self.failUnless( + self.assertTrue( do_nothing.mangled, "Mangled name of do_nothing function should be different +" "from None") @@ -198,7 +198,7 @@ def test_mangled_name_functions(self): def test_mangled_name_variable(self): # This works with gccxml and castxml var_inst = self.global_ns.variable('array255') - self.failUnless( + self.assertTrue( var_inst.mangled, "Mangled name of array255 variable should be different +" "from None") @@ -208,7 +208,7 @@ def test_demangled_name_variable(self): # raised when using castxml. var_inst = self.global_ns.variable('array255') if "GCC" in utils.xml_generator: - self.failUnless( + self.assertTrue( var_inst.demangled, "Demangled name of array255 variable should be different +" "from None") @@ -220,7 +220,7 @@ def test_demangled_name_variable(self): def _test_is_based_and_derived(self, base, derived, access): dhi_v = declarations.hierarchy_info_t(derived, access, True) dhi_not_v = declarations.hierarchy_info_t(derived, access, False) - self.failUnless( + self.assertTrue( dhi_v in base.derived or dhi_not_v in base.derived, "base class '%s' doesn't has derived class '%s'" % (base.name, derived.name)) @@ -228,7 +228,7 @@ def _test_is_based_and_derived(self, base, derived, access): bhi_v = declarations.hierarchy_info_t(base, access, True) bhi_not_v = declarations.hierarchy_info_t(base, access, False) - self.failUnless( + self.assertTrue( bhi_v in derived.bases or bhi_not_v in derived.bases, "derive class '%s' doesn't has base class '%s'" % (derived.name, base.name)) @@ -273,7 +273,7 @@ def _test_is_same_bases(self, derived1, derived2): for hierarchy_info in derived1.bases]) bases2 = set([id(hierarchy_info.related_class) for hierarchy_info in derived2.bases]) - self.failUnless( + self.assertTrue( bases1 == bases2, ("derived class '%s' and derived class '%s' has references to " + "different instance of base classes ") % @@ -321,7 +321,7 @@ def test_fundamental_types(self): typedef = self.global_ns.decl( decl_type=declarations.typedef_t, name=typedef_name) - self.failUnless( + self.assertTrue( typedef, "unable to find typedef to build-in type '%s'" % fundamental_type_name) @@ -390,14 +390,14 @@ def test_compound_types(self): typedef_inst = self.global_ns.decl( decl_type=declarations.typedef_t, name='typedef_EFavoriteDrinks') - self.failUnless( + self.assertTrue( isinstance( typedef_inst.type, declarations.declarated_t), " typedef to enum should be 'declarated_t' instead of '%s'" % typedef_inst.type.__class__.__name__) enum_declaration = self.global_ns.enum('EFavoriteDrinks') - self.failUnless( + self.assertTrue( typedef_inst.type.declaration is enum_declaration, "instance of declaration_t has reference to '%s' instead of '%s'" % (typedef_inst.type.declaration.name, @@ -412,26 +412,26 @@ def test_free_function_type(self): declarations.pointer_t, declarations.free_function_type_t) function_type = function_ptr.type.base - self.failUnless( + self.assertTrue( isinstance( function_type.return_type, declarations.int_t), "return function type of typedef 'function_ptr' should be " + "'%s' instead of '%s' " % ('int_t', function_type.return_type.__class__.__name__)) - self.failUnless( + self.assertTrue( len(function_type.arguments_types) == 2, "number of arguments of function of typedef 'function_ptr' " + "should be 2 instead of '%d' " % len(function_type.arguments_types)) - self.failUnless( + self.assertTrue( isinstance( function_type.arguments_types[0], declarations.int_t), "first argument of function of typedef 'function_ptr' should be " + "'%s' instead of '%s' " % ('int_t', function_type.arguments_types[0].__class__.__name__)) - self.failUnless( + self.assertTrue( isinstance( function_type.arguments_types[1], declarations.double_t), @@ -451,26 +451,26 @@ def test_member_function_type(self): function_type = function_ptr.type.base members_pointers = self.global_ns.class_('members_pointers_t') - self.failUnless( + self.assertTrue( function_type.class_inst.declaration is members_pointers, "member function type class should be '%s' instead of '%s'" % (members_pointers.decl_string, function_type.class_inst.decl_string)) - self.failUnless( + self.assertTrue( isinstance( function_type.return_type, declarations.int_t), "return function type of typedef 'member_function_ptr_t' should " + "be '%s' instead of '%s' " % ('int_t', function_type.return_type.__class__.__name__)) - self.failUnless( + self.assertTrue( len( function_type.arguments_types) == 1, "number of arguments of function of typedef " + "'member_function_ptr_t' should be 1 instead of '%d' " % len( function_type.arguments_types)) - self.failUnless( + self.assertTrue( isinstance( function_type.arguments_types[0], declarations.double_t), @@ -478,7 +478,7 @@ def test_member_function_type(self): "should be '%s' instead of '%s' " % ('double_t', function_type.arguments_types[0].__class__.__name__)) - self.failUnless( + self.assertTrue( function_type.has_const, " 'member_function_ptr_t' should be const function.") @@ -492,7 +492,7 @@ def test_member_variable_type(self): declarations.member_variable_type_t) members_pointers = self.global_ns.class_('members_pointers_t') - self.failUnless( + self.assertTrue( members_pointers, "unable to find class('%s')" % 'members_pointers_t') @@ -501,7 +501,7 @@ def test_member_variable_type(self): declarations.member_variable_type_t, declarations.declarated_t) mv_type = mv.type.base - self.failUnless( + self.assertTrue( mv_type.base.declaration is members_pointers, "member function type class should be '%s' instead of '%s'" % (members_pointers.decl_string, @@ -511,7 +511,7 @@ def test_overloading(self): ns = self.global_ns.namespace('overloads') do_nothings = ns.calldefs('do_nothing', recursive=False) - self.failUnless( + self.assertTrue( 4 == len(do_nothings), ("expected number of overloaded 'do_nothing' functions is %d " + "and existing(%d) is different") % @@ -526,39 +526,39 @@ def test_overloading(self): for x in others: print(str(x)) - self.failUnless(set(do_nothing.overloads) == set( + self.assertTrue(set(do_nothing.overloads) == set( others), "there is a difference between expected function " + "overloads and existing ones.") def test_abstract_classes(self): ns = self.global_ns.namespace('abstract_classes') abstract_i = ns.class_('abstract_i') - self.failUnless( + self.assertTrue( abstract_i.is_abstract, "class 'abstract_i' should be abstract") derived_abstract_i = ns.class_('derived_abstract_i') - self.failUnless( + self.assertTrue( derived_abstract_i.is_abstract, "class 'derived_abstract_i' should be abstract") implementation = ns.class_('implementation') - self.failUnless( + self.assertTrue( not implementation.is_abstract, "class 'implementation' should not be abstract") def test_versioning(self): - self.failUnless(utils.xml_generator) + self.assertTrue(utils.xml_generator) def test_byte_size(self): mptrs = self.global_ns.class_('members_pointers_t') - self.failUnless(mptrs.byte_size != 0) + self.assertTrue(mptrs.byte_size != 0) def test_byte_align(self): mptrs = self.global_ns.class_('members_pointers_t') - self.failUnless(mptrs.byte_align != 0) + self.assertTrue(mptrs.byte_align != 0) def test_byte_offset(self): mptrs = self.global_ns.class_('members_pointers_t') - self.failUnless(mptrs.variable('xxx').byte_offset != 0) + self.assertTrue(mptrs.variable('xxx').byte_offset != 0) class core_gccxml_t(core_t): diff --git a/unittests/decl_string_tester.py b/unittests/decl_string_tester.py index 985a0682..1c7540c1 100644 --- a/unittests/decl_string_tester.py +++ b/unittests/decl_string_tester.py @@ -38,7 +38,7 @@ def test_member_function(self): self.template % member_inline_call.decl_string, self.config) - self.failUnless( + self.assertTrue( decls, "Created decl_string for member function contains mistake") @@ -48,7 +48,7 @@ def test_free_function(self): self.template % return_default_args.decl_string, self.config) - self.failUnless( + self.assertTrue( decls, "Created decl_string for global function contains mistake") @@ -57,13 +57,13 @@ def test_all_mem_and_free_funs(self): for f in ns.mem_funs(): decls = parser.parse_string( self.template % f.decl_string, self.config) - self.failUnless( + self.assertTrue( decls, "Created decl_string for member function contains mistake") for f in ns.free_funs(): decls = parser.parse_string( self.template % f.decl_string, self.config) - self.failUnless( + self.assertTrue( decls, "Created decl_string for member function contains mistake") diff --git a/unittests/declaration_files_tester.py b/unittests/declaration_files_tester.py index eabffa9a..9ef23377 100644 --- a/unittests/declaration_files_tester.py +++ b/unittests/declaration_files_tester.py @@ -37,7 +37,7 @@ def test(self): result = set() for fn in files: result.add(os.path.split(fn)[1]) - self.failUnless(set(self.__files).issubset(result)) + self.assertTrue(set(self.__files).issubset(result)) def create_suite(): diff --git a/unittests/declaration_matcher_tester.py b/unittests/declaration_matcher_tester.py index daa6c588..dd14af75 100644 --- a/unittests/declaration_matcher_tester.py +++ b/unittests/declaration_matcher_tester.py @@ -36,10 +36,10 @@ def test_ns1(self): ns1 = gns.namespace('ns') gns.class_('nested_cls') - self.failUnlessRaises(Exception, lambda: gns.class_('ns::nested_cls')) + self.assertTrueRaises(Exception, lambda: gns.class_('ns::nested_cls')) gns.class_('::ns::nested_cls') - self.failUnlessRaises(Exception, lambda: ns1.class_('::nested_cls')) + self.assertTrueRaises(Exception, lambda: ns1.class_('::nested_cls')) ns1.class_('nested_cls') ns1.class_('::ns::nested_cls') diff --git a/unittests/declarations_comparison_tester.py b/unittests/declarations_comparison_tester.py index c0e32b99..16b3ef11 100644 --- a/unittests/declarations_comparison_tester.py +++ b/unittests/declarations_comparison_tester.py @@ -34,7 +34,7 @@ def test_comparison_declaration_by_declaration(self): "properly in case of %s, %s, index %d") % (parsed_decl.__class__.__name__, copied_decl.__class__.__name__, index)) - self.failUnless(not failuers, 'Failures: ' + '\n\t'.join(failuers)) + self.assertTrue(not failuers, 'Failures: ' + '\n\t'.join(failuers)) def test_comparison_from_reverse(self): parsed = parser.parse([self.header], self.config) @@ -46,7 +46,7 @@ def test_comparison_from_reverse(self): x.sort() y = copied[4:6] y.sort() - self.failUnless( + self.assertTrue( parsed == copied, "__lt__ and/or __qe__ does not working properly") @@ -60,12 +60,12 @@ def test___lt__transitivnost(self): right2left = [ns_global, ns_std] left2right.sort() right2left.sort() - self.failUnless(left2right == right2left, "bug: find me") + self.assertTrue(left2right == right2left, "bug: find me") def test_same_declarations_different_intances(self): parsed = parser.parse([self.header], self.config) copied = copy.deepcopy(parsed) - self.failUnless( + self.assertTrue( parsed == copied, "__lt__ and/or __qe__ does not working properly") diff --git a/unittests/declarations_tester.py b/unittests/declarations_tester.py index a36eb754..ac0e884b 100644 --- a/unittests/declarations_tester.py +++ b/unittests/declarations_tester.py @@ -24,7 +24,7 @@ def test_enumeration_t(self): expected_values = list( zip(['e%d' % index for index in range(10)], [index for index in range(10)])) - self.failUnless( + self.assertTrue( expected_values == enum.values, ("expected enum values ( '%s' ) and existings ( '%s' ) are " + "different") % @@ -46,7 +46,7 @@ def test_variables(self): else: expected_value = '10122004' - self.failUnless( + self.assertTrue( initialized.value == expected_value, ("there is a difference between expected value( %s ) and real " + "value(%s) of 'initialized' variable") % @@ -57,10 +57,10 @@ def test_variables(self): declarations.long_unsigned_int_t) static_var = initialized = self.global_ns.variable(name='static_var') - self.failUnless( + self.assertTrue( static_var.type_qualifiers.has_static, "static_var must have static type qualifier") - self.failUnless( + self.assertTrue( not static_var.type_qualifiers.has_mutable, "static_var must not have mutable type qualifier") @@ -68,11 +68,11 @@ def test_variables(self): return # TODO find out work around m_mutable = initialized = self.global_ns.variable(name='m_mutable') - self.failUnless( + self.assertTrue( not m_mutable.type_qualifiers.has_static, "m_mutable must not have static type qualifier") # TODO: "There is bug in GCCXML: doesn't write mutable qualifier." - # self.failUnless( m_mutable.type_qualifiers.has_mutable + # self.assertTrue( m_mutable.type_qualifiers.has_mutable # , "static_var must have mutable type qualifier" ) def test_calldef_free_functions(self): @@ -87,18 +87,18 @@ def test_calldef_free_functions(self): # gccxml will be dropped one day. With castxml check if function has # no extern qualifier. if 'GCC-XML' in utils.xml_generator: - self.failUnless( + self.assertTrue( no_return_no_args.has_extern, "function 'no_return_no_args' should have an extern qualifier") else: - self.failUnless( + self.assertTrue( not no_return_no_args.has_extern, "function 'no_return_no_args' should have an extern qualifier") # Static_call is explicetely defined as extern, this works with gccxml # and castxml. static_call = ns.free_function('static_call') - self.failUnless( + self.assertTrue( static_call, "function 'no_return_no_args' should have an extern qualifier") @@ -106,10 +106,10 @@ def test_calldef_free_functions(self): self._test_calldef_return_type(return_no_args, declarations.int_t) # from now there is no need to check return type. no_return_1_arg = ns.free_function(name='no_return_1_arg') - self.failUnless( + self.assertTrue( no_return_1_arg, "unable to find 'no_return_1_arg' function") - self.failUnless(no_return_1_arg.arguments[0].name in ['arg', 'arg0']) + self.assertTrue(no_return_1_arg.arguments[0].name in ['arg', 'arg0']) self._test_calldef_args( no_return_1_arg, [declarations.argument_t( @@ -117,9 +117,9 @@ def test_calldef_free_functions(self): type=declarations.int_t())]) return_default_args = ns.free_function('return_default_args') - self.failUnless( + self.assertTrue( return_default_args.arguments[0].name in ['arg', 'arg0']) - self.failUnless( + self.assertTrue( return_default_args.arguments[1].name in ['arg1', 'flag']) self._test_calldef_args( return_default_args, @@ -134,7 +134,7 @@ def test_calldef_free_functions(self): self._test_calldef_exceptions(return_default_args, []) calldef_with_throw = ns.free_function('calldef_with_throw') - self.failUnless( + self.assertTrue( calldef_with_throw, "unable to find 'calldef_with_throw' function") self._test_calldef_exceptions( @@ -154,31 +154,31 @@ def test_calldef_member_functions(self): member_const_call = struct_calldefs.member_function( 'member_const_call') - self.failUnless( + self.assertTrue( member_const_call.has_const, "function 'member_const_call' should have const qualifier") - self.failUnless( + self.assertTrue( member_const_call.virtuality == declarations.VIRTUALITY_TYPES.NOT_VIRTUAL, "function 'member_const_call' should be non virtual function") member_virtual_call = struct_calldefs.member_function( name='member_virtual_call') - self.failUnless( + self.assertTrue( member_virtual_call.virtuality == declarations.VIRTUALITY_TYPES.VIRTUAL, "function 'member_virtual_call' should be virtual function") member_pure_virtual_call = struct_calldefs.member_function( 'member_pure_virtual_call') - self.failUnless( + self.assertTrue( member_pure_virtual_call.virtuality == declarations.VIRTUALITY_TYPES.PURE_VIRTUAL, ("function 'member_pure_virtual_call' should be pure virtual " + "function")) static_call = struct_calldefs.member_function('static_call') - self.failUnless( + self.assertTrue( static_call.has_static, "function 'static_call' should have static qualifier") # from now we there is no need to check static qualifier @@ -198,13 +198,13 @@ def test_constructors_destructors(self): # 3. default # 4. copy constructor constructor_found = struct_calldefs.constructors('calldefs_t') - self.failUnless( + self.assertTrue( len(constructor_found) == 5, ("struct 'calldefs_t' has 5 constructors, pygccxml parser " + "reports only about %d.") % len(constructor_found)) error_text = "copy constructor has not been found" - self.failUnless(1 == len( + self.assertTrue(1 == len( [constructor for constructor in constructor_found if constructor.is_copy_constructor]), error_text) # there is nothing to check about constructors - I know the @@ -212,7 +212,7 @@ def test_constructors_destructors(self): # In this case it doesn't different from any other function c = struct_calldefs.constructor('calldefs_t', arg_types=['char']) - self.failUnless( + self.assertTrue( c.explicit, ("calldef_t constructor defined with 'explicit' keyword, " + "for some reason the value is False ")) @@ -220,7 +220,7 @@ def test_constructors_destructors(self): arg_type = declarations.declarated_t( self.global_ns.class_('some_exception_t')) c = struct_calldefs.constructor('calldefs_t', arg_types=[arg_type]) - self.failUnless( + self.assertTrue( c.explicit is False, ("calldef_t constructor defined without 'explicit' keyword, " + "for some reason the value is True ")) @@ -229,17 +229,17 @@ def test_operator_symbol(self): calldefs_operators = ['=', '=='] calldefs_cast_operators = ['char *', 'double'] struct_calldefs = self.global_ns.class_('calldefs_t') - self.failUnless(struct_calldefs, "unable to find struct 'calldefs_t'") + self.assertTrue(struct_calldefs, "unable to find struct 'calldefs_t'") for decl in struct_calldefs.declarations: if not isinstance(decl, declarations.operator_t): continue if not isinstance(decl, declarations.casting_operator_t): - self.failUnless( + self.assertTrue( decl.symbol in calldefs_operators, "unable to find operator symbol for operator '%s'" % decl.decl_string) else: - self.failUnless( + self.assertTrue( decl.return_type.decl_string in calldefs_cast_operators, "unable to find operator symbol for operator '%s'" % decl.decl_string) @@ -247,9 +247,9 @@ def test_operator_symbol(self): def test_ellipsis(self): ns = self.global_ns.ns('ellipsis_tester') do_smth = ns.mem_fun('do_smth') - self.failUnless(do_smth.has_ellipsis) + self.assertTrue(do_smth.has_ellipsis) do_smth_else = ns.free_fun('do_smth_else') - self.failUnless(do_smth_else.has_ellipsis) + self.assertTrue(do_smth_else.has_ellipsis) class gccxml_declarations_t(declarations_t): diff --git a/unittests/demangled_tester.py b/unittests/demangled_tester.py index 6dadf9ed..403c59b2 100644 --- a/unittests/demangled_tester.py +++ b/unittests/demangled_tester.py @@ -48,28 +48,28 @@ def test(self): if 0: # platform.machine() == 'x86_64': cls = demangled.class_( 'item_t<25214903917ul, 11ul, 2147483648ul>') - self.failUnless( + self.assertTrue( cls._name == 'item_t<25214903917ul,11ul,2147483648ul>', cls._name) else: cls = demangled.class_( 'item_t<3740067437ul, 11ul, 2147483648ul>') - self.failUnless( + self.assertTrue( cls._name == 'item_t<3740067437ul,11ul,2147483648ul>') else: cls = demangled.class_('item_t<3740067437l, 11l, 2147483648l>') - self.failUnless( + self.assertTrue( cls._name == 'item_t<0x0deece66d,11,0x080000000>') else: cls = demangled.class_("item_t<25214903917l, 11l, 2147483648l>") - self.failUnless(cls._name == 'item_t<25214903917,11,2147483648>') + self.assertTrue(cls._name == 'item_t<25214903917,11,2147483648>') def test_free_function(self): f = self.global_ns.free_functions('set_a', allow_empty=True) if not f: return f = f[0] - self.failUnless(f.mangled) + self.assertTrue(f.mangled) class tester_32_t(tester_impl_t): diff --git a/unittests/dependencies_tester.py b/unittests/dependencies_tester.py index f6b27b16..db746bab 100644 --- a/unittests/dependencies_tester.py +++ b/unittests/dependencies_tester.py @@ -30,15 +30,15 @@ def test_variable(self): ns_vars = self.global_ns.namespace('::declarations::variables') static_var = ns_vars.variable('static_var') dependencies = static_var.i_depend_on_them() - self.failUnless(len(dependencies) == 1) - self.failUnless(dependencies[0].declaration is static_var) - self.failUnless(dependencies[0].depend_on_it.decl_string == 'int') + self.assertTrue(len(dependencies) == 1) + self.assertTrue(dependencies[0].declaration is static_var) + self.assertTrue(dependencies[0].depend_on_it.decl_string == 'int') m_mutable = ns_vars.variable('m_mutable') dependencies = m_mutable.i_depend_on_them() - self.failUnless(len(dependencies) == 1) - self.failUnless(dependencies[0].declaration is m_mutable) - self.failUnless(dependencies[0].depend_on_it.decl_string == 'int') + self.assertTrue(len(dependencies) == 1) + self.assertTrue(dependencies[0].declaration is m_mutable) + self.assertTrue(dependencies[0].depend_on_it.decl_string == 'int') def test_class(self): ns_vars = self.global_ns.namespace('::declarations::variables') @@ -50,18 +50,18 @@ def test_class(self): # and operator= to the class, if it has dependencies = [ d for d in dependencies if not d.declaration.is_artificial] - self.failUnless(len(dependencies) == 1) + self.assertTrue(len(dependencies) == 1) else: # compiler generated copy constructor - self.failUnless(len(dependencies) == 2) + self.assertTrue(len(dependencies) == 2) m_mutable = ns_vars.variable('m_mutable') dependencies = [ dependency for dependency in dependencies if dependency.declaration is m_mutable] - self.failUnless(len(dependencies) == 1) - self.failUnless(dependencies[0].depend_on_it.decl_string == 'int') - self.failUnless(dependencies[0].access_type == 'public') + self.assertTrue(len(dependencies) == 1) + self.assertTrue(dependencies[0].depend_on_it.decl_string == 'int') + self.assertTrue(dependencies[0].access_type == 'public') ns_dh = self.global_ns.namespace('::core::diamand_hierarchy') fd_cls = ns_dh.class_('final_derived_t') @@ -70,28 +70,28 @@ def test_class(self): dependencies = [ dependency for dependency in dependencies if dependency.depend_on_it is derived1_cls] - self.failUnless(len(dependencies) == 1) - self.failUnless(dependencies[0].depend_on_it is derived1_cls) - self.failUnless(dependencies[0].access_type == 'public') + self.assertTrue(len(dependencies) == 1) + self.assertTrue(dependencies[0].depend_on_it is derived1_cls) + self.assertTrue(dependencies[0].access_type == 'public') def test_calldefs(self): ns = self.global_ns.namespace('::declarations::calldef') return_default_args = ns.calldef('return_default_args') dependencies = return_default_args.i_depend_on_them() - self.failUnless(len(dependencies) == 3) + self.assertTrue(len(dependencies) == 3) used_types = [ dependency.depend_on_it.decl_string for dependency in dependencies] - self.failUnless(used_types == ['int', 'int', 'bool']) + self.assertTrue(used_types == ['int', 'int', 'bool']) some_exception = ns.class_('some_exception_t') other_exception = ns.class_('other_exception_t') calldef_with_throw = ns.calldef('calldef_with_throw') dependencies = calldef_with_throw.i_depend_on_them() - self.failUnless(len(dependencies) == 3) + self.assertTrue(len(dependencies) == 3) dependencies = [ dependency for dependency in dependencies if dependency.depend_on_it in (some_exception, other_exception)] - self.failUnless(len(dependencies) == 2) + self.assertTrue(len(dependencies) == 2) def test_coverage(self): self.global_ns.i_depend_on_them() diff --git a/unittests/file_cache_tester.py b/unittests/file_cache_tester.py index c108032e..3ab3603f 100644 --- a/unittests/file_cache_tester.py +++ b/unittests/file_cache_tester.py @@ -40,13 +40,13 @@ def test_update(self): configuration=self.config, declarations=declarations, included_files=[]) - self.failUnless( + self.assertTrue( declarations == cache.cached_value( self.header, self.config), "cached declarations and source declarations are different") self.touch() - self.failUnless( + self.assertTrue( cache.cached_value(self.header, self.config) is None, "cache didn't recognize that some files on disk has been changed") @@ -64,14 +64,14 @@ def test_from_file(self): configuration=self.config, declarations=declarations, included_files=[]) - self.failUnless( + self.assertTrue( declarations == cache.cached_value( self.header, self.config), "cached declarations and source declarations are different") cache.flush() cache = parser.file_cache_t(self.cache_file) - self.failUnless( + self.assertTrue( declarations == cache.cached_value( self.header, self.config), diff --git a/unittests/filters_tester.py b/unittests/filters_tester.py index 015ad9e3..92799463 100644 --- a/unittests/filters_tester.py +++ b/unittests/filters_tester.py @@ -33,7 +33,7 @@ def test_regex(self): lambda decl: decl.name) operators = declarations.matcher.find(criteria, self.global_ns) operators = [d for d in operators if not d.is_artificial] - self.failUnless(6 == len(operators)) + self.assertTrue(6 == len(operators)) def test_access_type(self): criteria = declarations.access_type_matcher_t( @@ -41,12 +41,12 @@ def test_access_type(self): public_members = declarations.matcher.find(criteria, self.global_ns) if "CastXML" in utils.xml_generator: public_members = [d for d in public_members if not d.is_artificial] - self.failUnless(21 == len(public_members)) + self.assertTrue(21 == len(public_members)) if "0.9" in utils.xml_generator: public_members = [d for d in public_members if not d.is_artificial] - self.failUnless(17 == len(public_members)) + self.assertTrue(17 == len(public_members)) else: - self.failUnless(21 == len(public_members)) + self.assertTrue(21 == len(public_members)) def test_or_matcher(self): criteria1 = declarations.regex_matcher_t( @@ -60,12 +60,12 @@ def test_or_matcher(self): if "CastXML" in utils.xml_generator: found = [d for d in found if not d.is_artificial] - self.failUnless(len(found) != 35) + self.assertTrue(len(found) != 35) elif "0.9" in utils.xml_generator: found = [d for d in found if not d.is_artificial] - self.failUnless(15 <= len(found) <= 21) + self.assertTrue(15 <= len(found) <= 21) else: - self.failUnless(19 <= len(found) <= 25) + self.assertTrue(19 <= len(found) <= 25) def test_and_matcher(self): criteria1 = declarations.regex_matcher_t( @@ -77,7 +77,7 @@ def test_and_matcher(self): criteria1 & criteria2, self.global_ns) found = [d for d in found if not d.is_artificial] - self.failUnless(len(found) <= 6) + self.assertTrue(len(found) <= 6) def test_not_matcher(self): criteria1 = declarations.regex_matcher_t( @@ -85,7 +85,7 @@ def test_not_matcher(self): lambda decl: decl.name) found = declarations.matcher.find(~(~criteria1), self.global_ns) found = [d for d in found if not d.is_artificial] - self.failUnless(len(found) == 6) + self.assertTrue(len(found) == 6) def create_suite(): diff --git a/unittests/find_container_traits_tester.py b/unittests/find_container_traits_tester.py index cff86be8..38220ef5 100644 --- a/unittests/find_container_traits_tester.py +++ b/unittests/find_container_traits_tester.py @@ -27,39 +27,39 @@ def __cmp_traits(self, typedef, expected, partial_name, key_type=None): if utils.is_str(typedef): typedef = self.global_ns.typedef(typedef) traits = declarations.find_container_traits(typedef) - self.failUnless( + self.assertTrue( traits, 'container traits for "%s" not found' % str(typedef)) - self.failUnless( + self.assertTrue( traits is expected, 'container "%s", expected %s_traits, got %s_traits' % (str(typedef), expected.name(), traits.name())) cls = declarations.remove_declarated(typedef) - self.failUnless(cls.container_traits is expected) - self.failUnless(cls.partial_name == partial_name) + self.assertTrue(cls.container_traits is expected) + self.assertTrue(cls.partial_name == partial_name) cls = traits.class_declaration(cls) - self.failUnless(traits.element_type(typedef)) - self.failUnless( + self.assertTrue(traits.element_type(typedef)) + self.assertTrue( cls.cache.container_element_type, "For some reason cache was not updated") if key_type: - self.failUnless(traits.is_mapping(typedef)) + self.assertTrue(traits.is_mapping(typedef)) real_key_type = traits.key_type(typedef) - self.failUnless( + self.assertTrue( real_key_type.decl_string == key_type, 'Error extracting key type. Expected type "%s", got "%s"' % (key_type, real_key_type.decl_string)) - self.failUnless( + self.assertTrue( cls.cache.container_key_type, "For some reason cache was not updated") else: - self.failUnless(traits.is_sequence(typedef)) + self.assertTrue(traits.is_sequence(typedef)) def test_find_traits(self): self.__cmp_traits('v_int', declarations.vector_traits, "vector< int >") @@ -144,12 +144,12 @@ def test_multimap(self): m = self.global_ns.class_( lambda decl: decl.name.startswith('multimap')) declarations.find_container_traits(m) - self.failUnless(m.partial_name == 'multimap< int, int >') + self.assertTrue(m.partial_name == 'multimap< int, int >') def test_recursive_partial_name(self): f1 = self.global_ns.free_fun('f1') t1 = declarations.class_traits.get_declaration(f1.arguments[0].type) - self.failUnless( + self.assertTrue( 'type< std::set< std::vector< int > > >' == t1.partial_name) def test_remove_defaults_partial_name_namespace(self): @@ -181,9 +181,9 @@ def test_from_ogre(self): def test_infinite_loop(self): rt = self.global_ns.free_fun('test_infinite_loop').return_type map_traits = declarations.find_container_traits(rt) - self.failUnless(map_traits is declarations.map_traits) + self.assertTrue(map_traits is declarations.map_traits) elem = map_traits.element_type(rt) - self.failUnless(elem.decl_string == 'int') + self.assertTrue(elem.decl_string == 'int') def create_suite(): diff --git a/unittests/free_operators_tester.py b/unittests/free_operators_tester.py index 6fae0c63..9f0bf02f 100644 --- a/unittests/free_operators_tester.py +++ b/unittests/free_operators_tester.py @@ -27,9 +27,9 @@ def test(self): rational = fo.class_('rational') for oper in fo.free_operators(): if number.name in str(oper): - self.failUnless(number in oper.class_types) + self.assertTrue(number in oper.class_types) if rational.name in str(oper): - self.failUnless(rational in oper.class_types) + self.assertTrue(rational in oper.class_types) def create_suite(): diff --git a/unittests/function_traits_tester.py b/unittests/function_traits_tester.py index 482f5cef..1a6eb9cf 100644 --- a/unittests/function_traits_tester.py +++ b/unittests/function_traits_tester.py @@ -31,7 +31,7 @@ def test_is_same_function(self): df = d.mem_fun('f') bf = b.mem_fun('f') - self.failUnless( + self.assertTrue( id(df) != id(bf) and declarations.is_same_function(df, bf)) diff --git a/unittests/gccxml10183_tester.py b/unittests/gccxml10183_tester.py index 92189cbb..1562042a 100644 --- a/unittests/gccxml10183_tester.py +++ b/unittests/gccxml10183_tester.py @@ -33,7 +33,7 @@ def test(self): if 'GCCXML' in utils.xml_generator: global_ns.decl('A') f = global_ns.free_fun('f') - self.failUnless(f.demangled == 'void f(A const&)') + self.assertTrue(f.demangled == 'void f(A const&)') def create_suite(): diff --git a/unittests/gccxml10184_tester.py b/unittests/gccxml10184_tester.py index c53ef13b..5333abf5 100644 --- a/unittests/gccxml10184_tester.py +++ b/unittests/gccxml10184_tester.py @@ -28,8 +28,8 @@ def test(self): src_reader = parser.source_reader_t(self.config) global_ns = declarations.get_global_namespace( src_reader.read_string(code)) - self.failUnless(global_ns.variable('a').bits == 1) - self.failUnless(global_ns.variable('unused').bits == 31) + self.assertTrue(global_ns.variable('a').bits == 1) + self.assertTrue(global_ns.variable('unused').bits == 31) def create_suite(): diff --git a/unittests/gccxml_runner_tester.py b/unittests/gccxml_runner_tester.py index 45c8a8f9..f6924dcb 100644 --- a/unittests/gccxml_runner_tester.py +++ b/unittests/gccxml_runner_tester.py @@ -17,7 +17,7 @@ def __init__(self, *args): self.content = "abra cadabra " + os.linesep def test_gccxml_on_input_with_errors(self): - self.failUnlessRaises( + self.assertTrueRaises( RuntimeError, parser.parse_string, self.content, diff --git a/unittests/has_binary_operator_traits_tester.py b/unittests/has_binary_operator_traits_tester.py index 2668b245..77abbaed 100644 --- a/unittests/has_binary_operator_traits_tester.py +++ b/unittests/has_binary_operator_traits_tester.py @@ -28,7 +28,7 @@ def setUp(self): def test_yes(self): yes_ns = self.global_ns.namespace('yes') for typedef in yes_ns.typedefs(): - self.failUnless( + self.assertTrue( declarations.has_public_equal(typedef), "Class '%s' should have public operator==" % typedef.decl_string) @@ -36,7 +36,7 @@ def test_yes(self): def test_no(self): no_ns = self.global_ns.namespace('no') for typedef in no_ns.typedefs(): - self.failUnless( + self.assertTrue( not declarations.has_public_equal(typedef), "Class '%s' should not have public operator==" % typedef.decl_string) diff --git a/unittests/hierarchy_traveling.py b/unittests/hierarchy_traveling.py index 32f9d90d..74c7aa20 100644 --- a/unittests/hierarchy_traveling.py +++ b/unittests/hierarchy_traveling.py @@ -58,12 +58,12 @@ def test_recursive_bases(self): # With CastXML; there is a __va_list_tag which is generated by # clang. Do not run the tests for it. continue - self.failUnless(class_.name in self.__recursive_bases) + self.assertTrue(class_.name in self.__recursive_bases) all_bases = class_.recursive_bases control_bases = self.__recursive_bases[class_.name] - self.failUnless(len(control_bases) == len(all_bases)) + self.assertTrue(len(control_bases) == len(all_bases)) all_bases_names = [hi.related_class.name for hi in all_bases] - self.failUnless(set(all_bases_names) == control_bases) + self.assertTrue(set(all_bases_names) == control_bases) def test_recursive_derived(self): src_reader = parser.source_reader_t(self.config) @@ -78,12 +78,12 @@ def test_recursive_derived(self): # With CastXML; there is a __va_list_tag which is generated by # clang. Do not run the tests for it. continue - self.failUnless(class_.name in self.__recursive_derived) + self.assertTrue(class_.name in self.__recursive_derived) all_derived = class_.recursive_derived control_derived = self.__recursive_derived[class_.name] - self.failUnless(len(control_derived) == len(all_derived)) + self.assertTrue(len(control_derived) == len(all_derived)) all_derived_names = [hi.related_class.name for hi in all_derived] - self.failUnless(set(all_derived_names) == control_derived) + self.assertTrue(set(all_derived_names) == control_derived) pass diff --git a/unittests/inline_specifier_tester.py b/unittests/inline_specifier_tester.py index ec335dea..7e85bbcc 100644 --- a/unittests/inline_specifier_tester.py +++ b/unittests/inline_specifier_tester.py @@ -25,14 +25,14 @@ def setUp(self): def test(self): inlined_funcs = self.global_ns.calldefs('inlined') - self.failUnless(len(inlined_funcs)) + self.assertTrue(len(inlined_funcs)) for f in inlined_funcs: - self.failUnless(f.has_inline) + self.assertTrue(f.has_inline) not_inlined_funcs = self.global_ns.calldefs('not_inlined') - self.failUnless(len(not_inlined_funcs)) + self.assertTrue(len(not_inlined_funcs)) for f in not_inlined_funcs: - self.failUnless(f.has_inline is False) + self.assertTrue(f.has_inline is False) def test2(self): pass diff --git a/unittests/namespace_matcher_tester.py b/unittests/namespace_matcher_tester.py index 563e8b47..f8100189 100644 --- a/unittests/namespace_matcher_tester.py +++ b/unittests/namespace_matcher_tester.py @@ -24,13 +24,13 @@ def setUp(self): def test(self): criteria = declarations.namespace_matcher_t(name='bit_fields') declarations.matcher.get_single(criteria, self.declarations) - self.failUnless( + self.assertTrue( str(criteria) == '(decl type==namespace_t) and (name==bit_fields)') def test_allow_empty(self): global_ns = declarations.get_global_namespace(self.declarations) global_ns.init_optimizer() - self.failUnless( + self.assertTrue( 0 == len(global_ns.namespaces('does not exist', allow_empty=True))) diff --git a/unittests/parser_test_case.py b/unittests/parser_test_case.py index 95b13817..8cfbd6f4 100644 --- a/unittests/parser_test_case.py +++ b/unittests/parser_test_case.py @@ -25,17 +25,17 @@ def __init__(self, *args): pass def _test_type_composition(self, type_, expected_compound, expected_base): - self.failUnless( + self.assertTrue( isinstance(type_, expected_compound), "the compound type('%s') should be '%s'" % (type_.decl_string, expected_compound.__name__)) - self.failUnless( + self.assertTrue( isinstance(type_.base, expected_base), "base type('%s') should be '%s'" % (type_.decl_string, expected_base.__name__)) def _test_calldef_return_type(self, calldef, expected_type): - self.failUnless( + self.assertTrue( isinstance(calldef.return_type, expected_type), ("the function's '%s' expected return type is '%s' and in " + "reality it is different('%s')") % @@ -43,7 +43,7 @@ def _test_calldef_return_type(self, calldef, expected_type): calldef.return_type.__class__.__name__)) def _test_calldef_args(self, calldef, expected_args): - self.failUnless( + self.assertTrue( len(calldef.arguments) == len(expected_args), ("the function's '%s' expected number of arguments is '%d' and " + "in reality it is different('%d')") % @@ -51,7 +51,7 @@ def _test_calldef_args(self, calldef, expected_args): for i, expected_arg in enumerate(expected_args): arg = calldef.arguments[i] - self.failUnless( + self.assertTrue( arg == expected_arg, ("the function's '%s' expected %d's argument is '%s' and in " + "reality it is different('%s')") % @@ -63,13 +63,13 @@ def _test_calldef_exceptions(self, calldef, exceptions): exception_decls = [] for name in exceptions: exception_decl = self.global_ns.class_(name) - self.failUnless( + self.assertTrue( exception_decl, "unable to find exception class '%s'" % name) exception_decls.append(exception_decl) exception_decls.sort() - self.failUnless( + self.assertTrue( len(calldef.exceptions) == len(exception_decls), ("the function's '%s' expected number of exceptions is '%d' and " + "in reality it is different('%d')") % @@ -77,7 +77,7 @@ def _test_calldef_exceptions(self, calldef, exceptions): len(exception_decls), len(calldef.exceptions))) exceptions_indeed = sorted(calldef.exceptions[:]) - self.failUnless( + self.assertTrue( exception_decls == exceptions_indeed, ("the function's '%s' expected exceptions are '%s' and in " + "reality it is different('%s')") % diff --git a/unittests/patcher_tester.py b/unittests/patcher_tester.py index b2a7eb04..8e7ac2da 100644 --- a/unittests/patcher_tester.py +++ b/unittests/patcher_tester.py @@ -25,9 +25,9 @@ def test_enum_patcher(self): default_val = fix_enum.arguments[0].default_value if "CastXML" in utils.xml_generator: # Most clean output, no need to patch - self.failUnless(default_val == "ns1::ns2::apple") + self.assertTrue(default_val == "ns1::ns2::apple") else: - self.failUnless(default_val == "::ns1::ns2::apple") + self.assertTrue(default_val == "::ns1::ns2::apple") # double_call = declarations.find_declaration( # decls, type=declarations.free_function_t, name='double_call' ) @@ -37,33 +37,33 @@ def test_numeric_patcher(self): if 32 == self.architecture: if "0.9" in utils.xml_generator: if platform.machine() == "x86_64": - self.failUnless( + self.assertTrue( fix_numeric.arguments[0].default_value == "-1u", fix_numeric.arguments[0].default_value) else: val = "0xffffffffffffffffu" - self.failUnless( + self.assertTrue( fix_numeric.arguments[0].default_value == val, fix_numeric.arguments[0].default_value) else: val = "0xffffffffffffffff" - self.failUnless( + self.assertTrue( fix_numeric.arguments[0].default_value == val, fix_numeric.arguments[0].default_value) else: if "CastXML" in utils.xml_generator: # Most clean output, no need to patch - self.failUnless( + self.assertTrue( fix_numeric.arguments[0].default_value == "(ull)-1", fix_numeric.arguments[0].default_value) else: - self.failUnless( + self.assertTrue( fix_numeric.arguments[0].default_value == "0ffffffff", fix_numeric.arguments[0].default_value) def test_unnamed_enum_patcher(self): fix_unnamed = self.global_ns.free_fun("fix_unnamed") - self.failUnless( + self.assertTrue( fix_unnamed.arguments[0].default_value == "int(::fx::unnamed)") def test_function_call_patcher(self): @@ -72,18 +72,18 @@ def test_function_call_patcher(self): if "CastXML" in utils.xml_generator: # Most clean output, no need to patch val = "calc(1, 2, 3)" - self.failUnless(default_val == val) + self.assertTrue(default_val == val) elif "0.9" in utils.xml_generator: val = "function_call::calc(1, 2, 3)" - self.failUnless(default_val == val) + self.assertTrue(default_val == val) else: val = "function_call::calc( 1, 2, 3 )" - self.failUnless(default_val == val) + self.assertTrue(default_val == val) def test_fundamental_patcher(self): fcall = self.global_ns.free_fun("fix_fundamental") val = "(unsigned int)(::fundamental::eggs)" - self.failUnless( + self.assertTrue( fcall.arguments[0].default_value == val) def test_constructor_patcher(self): @@ -91,14 +91,14 @@ def test_constructor_patcher(self): default_val = typedef__func.arguments[0].default_value if "0.9" in utils.xml_generator: val = "typedef_::original_name()" - self.failUnless(default_val == val) + self.assertTrue(default_val == val) elif "CastXML" in utils.xml_generator: # Most clean output, no need to patch val = "typedef_::alias()" - self.failUnless(default_val == val) + self.assertTrue(default_val == val) else: val = "::typedef_::alias( )" - self.failUnless(default_val == val) + self.assertTrue(default_val == val) if 32 == self.architecture: clone_tree = self.global_ns.free_fun("clone_tree") default_values = [] @@ -116,7 +116,7 @@ def test_constructor_patcher(self): "std::allocator > > >((&allocator" + ", " + "std::allocator > >()))")] - self.failUnless( + self.assertTrue( clone_tree.arguments[0].default_value in default_values) diff --git a/unittests/plain_c_tester.py b/unittests/plain_c_tester.py index a68f6467..b76d48b5 100644 --- a/unittests/plain_c_tester.py +++ b/unittests/plain_c_tester.py @@ -27,7 +27,7 @@ def test(self): self.global_ns.free_fun('hello_print') f = self.global_ns.free_fun('do_smth') for arg in f.arguments: - self.failUnless(arg.type.decl_string) + self.assertTrue(arg.type.decl_string) def create_suite(): diff --git a/unittests/project_reader_correctness_tester.py b/unittests/project_reader_correctness_tester.py index 056da067..fdd346ef 100644 --- a/unittests/project_reader_correctness_tester.py +++ b/unittests/project_reader_correctness_tester.py @@ -86,7 +86,7 @@ def test(self): os.path.join( autoconfig.build_directory, 'separate_compilation.pr.txt')) - self.failUnless( + self.assertTrue( src_decls == prj_decls, "There is a difference between declarations") diff --git a/unittests/remove_template_defaults_tester.py b/unittests/remove_template_defaults_tester.py index 2e0cb152..257577dc 100644 --- a/unittests/remove_template_defaults_tester.py +++ b/unittests/remove_template_defaults_tester.py @@ -26,98 +26,98 @@ def setUp(self): def test_vector(self): v_int = self.global_ns.typedef('v_int') v_traits = declarations.vector_traits - self.failUnless('vector< int >' == v_traits.remove_defaults(v_int)) + self.assertTrue('vector< int >' == v_traits.remove_defaults(v_int)) v_string = self.global_ns.typedef('v_string') - self.failUnless( + self.assertTrue( 'vector< std::string >' == v_traits.remove_defaults(v_string)) v_v_int = self.global_ns.typedef('v_v_int') - self.failUnless( + self.assertTrue( 'vector< std::vector< int > >' == v_traits.remove_defaults(v_v_int)) def test_list(self): l_int = self.global_ns.typedef('l_int') l_traits = declarations.list_traits - self.failUnless('list< int >' == l_traits.remove_defaults(l_int)) + self.assertTrue('list< int >' == l_traits.remove_defaults(l_int)) l_wstring = self.global_ns.typedef('l_wstring') - self.failUnless( + self.assertTrue( 'list< std::wstring >' == l_traits.remove_defaults(l_wstring)) def test_deque(self): d_v_int = self.global_ns.typedef('d_v_int') d_v_traits = declarations.deque_traits - self.failUnless( + self.assertTrue( 'deque< std::vector< int > >' == d_v_traits.remove_defaults(d_v_int)) d_l_string = self.global_ns.typedef('d_l_string') - self.failUnless( + self.assertTrue( 'deque< std::list< std::string > >' == d_v_traits.remove_defaults(d_l_string)) def test_queue(self): q_int = self.global_ns.typedef('q_int') q_traits = declarations.queue_traits - self.failUnless('queue< int >' == q_traits.remove_defaults(q_int)) + self.assertTrue('queue< int >' == q_traits.remove_defaults(q_int)) q_string = self.global_ns.typedef('q_string') - self.failUnless( + self.assertTrue( 'queue< std::string >' == q_traits.remove_defaults(q_string)) def test_priority_queue(self): pq_int = self.global_ns.typedef('pq_int') pq_traits = declarations.priority_queue_traits - self.failUnless( + self.assertTrue( 'priority_queue< int >' == pq_traits.remove_defaults(pq_int)) pq_string = self.global_ns.typedef('pq_string') - self.failUnless( + self.assertTrue( 'priority_queue< std::string >' == pq_traits.remove_defaults(pq_string)) def test_set(self): s_v_int = self.global_ns.typedef('s_v_int') - self.failUnless( + self.assertTrue( 'set< std::vector< int > >' == declarations.set_traits.remove_defaults(s_v_int)) s_string = self.global_ns.typedef('s_string') - self.failUnless( + self.assertTrue( 'set< std::string >' == declarations.set_traits.remove_defaults(s_string)) def test_multiset(self): ms_v_int = self.global_ns.typedef('ms_v_int') ms_v_traits = declarations.multiset_traits - self.failUnless( + self.assertTrue( 'multiset< std::vector< int > >' == ms_v_traits.remove_defaults(ms_v_int)) ms_string = self.global_ns.typedef('ms_string') - self.failUnless( + self.assertTrue( 'multiset< std::string >' == ms_v_traits.remove_defaults(ms_string)) def test_map(self): m_i2d = self.global_ns.typedef('m_i2d') - self.failUnless( + self.assertTrue( 'map< int, double >' == declarations.map_traits.remove_defaults(m_i2d)) m_wstr2d = self.global_ns.typedef('m_wstr2d') - self.failUnless( + self.assertTrue( 'map< std::wstring, double >' == declarations.map_traits.remove_defaults(m_wstr2d)) m_v_i2m_wstr2d = self.global_ns.typedef('m_v_i2m_wstr2d') m = 'map< const std::vector< int >, std::map< std::wstring, double > >' - self.failUnless( + self.assertTrue( m == declarations.map_traits.remove_defaults(m_v_i2m_wstr2d)) def test_multimap(self): mm_i2d = self.global_ns.typedef('mm_i2d') mm_traits = declarations.multimap_traits - self.failUnless( + self.assertTrue( 'multimap< int, double >' == mm_traits.remove_defaults(mm_i2d)) mm_wstr2d = self.global_ns.typedef('mm_wstr2d') - self.failUnless( + self.assertTrue( 'multimap< const std::wstring, double >' == mm_traits.remove_defaults(mm_wstr2d)) mm_v_i2mm_wstr2d = self.global_ns.typedef('mm_v_i2mm_wstr2d') - self.failUnless( + self.assertTrue( ('multimap< const std::vector< int >, ' + 'const std::multimap< const std::wstring, double > >') == mm_traits.remove_defaults(mm_v_i2mm_wstr2d)) @@ -130,12 +130,12 @@ def test_hash_set(self): else: hs_traits = declarations.hash_set_traits name = 'hash_set' - self.failUnless( + self.assertTrue( (name + '< std::vector< int > >') == hs_traits.remove_defaults(hs_v_int), hs_traits.remove_defaults(hs_v_int)) hs_string = self.global_ns.typedef('hs_string') - self.failUnless( + self.assertTrue( (name + '< std::string >') == hs_traits.remove_defaults(hs_string)) def test_hash_multiset(self): @@ -146,11 +146,11 @@ def test_hash_multiset(self): else: mhs_traits = declarations.hash_multiset_traits name = 'hash_multiset' - self.failUnless( + self.assertTrue( (name + '< std::vector< int > >') == mhs_traits.remove_defaults(mhs_v_int)) mhs_string = self.global_ns.typedef('mhs_string') - self.failUnless( + self.assertTrue( (name + '< std::string >') == mhs_traits.remove_defaults(mhs_string)) @@ -162,10 +162,10 @@ def test_hash_map(self): else: hm_traits = declarations.hash_map_traits name = 'hash_map' - self.failUnless( + self.assertTrue( (name + '< int, double >') == hm_traits.remove_defaults(hm_i2d)) hm_wstr2d = self.global_ns.typedef('hm_wstr2d') - self.failUnless( + self.assertTrue( (name + '< std::wstring, double >') == hm_traits.remove_defaults(hm_wstr2d)) @@ -177,11 +177,11 @@ def test_hash_multimap(self): else: hmm_traits = declarations.hash_multimap_traits name = 'hash_multimap' - self.failUnless( + self.assertTrue( (name + '< int, double >') == hmm_traits.remove_defaults(hmm_i2d)) hmm_wstr2d = self.global_ns.typedef('hmm_wstr2d') - self.failUnless( + self.assertTrue( (name + '< const std::wstring, double >') == hmm_traits.remove_defaults(hmm_wstr2d)) @@ -198,7 +198,7 @@ def test_hash_multimap(self): name + '< const std::vector< int >, ' + 'const stdext::' + name + '< const std::wstring, double > >') - self.failUnless(hmm_traits_value in possible_values, hmm_traits_value) + self.assertTrue(hmm_traits_value in possible_values, hmm_traits_value) def create_suite(): diff --git a/unittests/source_reader_tester.py b/unittests/source_reader_tester.py index bb48cc93..306a1b07 100644 --- a/unittests/source_reader_tester.py +++ b/unittests/source_reader_tester.py @@ -27,7 +27,7 @@ def setUp(self): def test_compound_argument_type(self): do_smth = self.global_ns.calldefs('do_smth') - self.failUnless(do_smth, "unable to find do_smth") + self.assertTrue(do_smth, "unable to find do_smth") do_smth.function_type() diff --git a/unittests/start_with_declarations_tester.py b/unittests/start_with_declarations_tester.py index 718d04fc..13cc862f 100644 --- a/unittests/start_with_declarations_tester.py +++ b/unittests/start_with_declarations_tester.py @@ -21,13 +21,13 @@ def __init__(self, *args): def __check_result(self, decls): E11 = declarations.find_declaration(decls, fullname='::E11') - self.failUnless(E11, "unable to find 'E11' enum") + self.assertTrue(E11, "unable to find 'E11' enum") ns12 = declarations.find_declaration(decls, fullname='::ns::ns12') - self.failUnless(ns12, "unable to find 'ns12' namespace") + self.assertTrue(ns12, "unable to find 'ns12' namespace") E13 = declarations.find_declaration(ns12.declarations, name='E13') - self.failUnless(E13, "unable to find 'E13' enum") + self.assertTrue(E13, "unable to find 'E13' enum") E14 = declarations.find_declaration(decls, name='E14') - self.failUnless( + self.assertTrue( not E14, "enum 'E14' should not be found in declarations") diff --git a/unittests/string_traits_tester.py b/unittests/string_traits_tester.py index 854c5f4d..1dd50d4b 100644 --- a/unittests/string_traits_tester.py +++ b/unittests/string_traits_tester.py @@ -26,11 +26,11 @@ def setUp(self): def validate_yes(self, ns, controller): for typedef in ns.typedefs(): - self.failUnless(controller(typedef.type)) + self.assertTrue(controller(typedef.type)) def validate_no(self, ns, controller): for typedef in ns.typedefs(): - self.failUnless(not controller(typedef.type)) + self.assertTrue(not controller(typedef.type)) def test_string(self): string_traits = self.global_ns.namespace('string_traits') diff --git a/unittests/templates_tester.py b/unittests/templates_tester.py index e7846453..4a8546b9 100644 --- a/unittests/templates_tester.py +++ b/unittests/templates_tester.py @@ -14,15 +14,15 @@ def __init__(self, *args): unittest.TestCase.__init__(self, *args) def __test_split_impl(self, decl_string, name, args): - self.failUnless( + self.assertTrue( (name, args) == declarations.templates.split(decl_string)) def __test_split_recursive_impl(self, decl_string, control_seq): - self.failUnless( + self.assertTrue( control_seq == declarations.templates.split_recursive(decl_string)) def __test_is_template_impl(self, decl_string): - self.failUnless(declarations.templates.is_instantiation(decl_string)) + self.assertTrue(declarations.templates.is_instantiation(decl_string)) def test_split_on_vector(self): self.__test_is_template_impl("vector >") @@ -66,13 +66,13 @@ def test_split_on_map(self): "std::vector > > >"]) def test_join_on_vector(self): - self.failUnless( + self.assertTrue( "vector< int, std::allocator >" == declarations.templates.join( "vector", ("int", "std::allocator"))) def test_bug_is_tmpl_inst(self): - self.failUnless( + self.assertTrue( declarations.templates.is_instantiation( "::FX::QMemArray::setRawData") is False) @@ -83,7 +83,7 @@ def test_bug_is_tmpl_inst(self): # 'std::allocator > >' # name, args = declarations.templates.split( x ) - # self.failUnless( len(x) == 4, "This test is expected to fail." ) + # self.assertTrue( len(x) == 4, "This test is expected to fail." ) def create_suite(): diff --git a/unittests/test_create_decl_string.py b/unittests/test_create_decl_string.py index bee9ba38..65272740 100644 --- a/unittests/test_create_decl_string.py +++ b/unittests/test_create_decl_string.py @@ -33,7 +33,7 @@ def test(self): decl = declarations.free_function_type_t.create_decl_string( myfunc.return_type, myfunc.argument_types) - self.failUnless(decl != "('int (*)( int,int )', 'int (*)( int,int )')") + self.assertTrue(decl != "('int (*)( int,int )', 'int (*)( int,int )')") box = self.global_ns.class_("Box") myinternfunc = box.member_function("myinternfunc") @@ -43,7 +43,7 @@ def test(self): myinternfunc.argument_types, myinternfunc.has_const) - self.failUnless(decl != "short int ( ::Box::* )( ) ") + self.assertTrue(decl != "short int ( ::Box::* )( ) ") def create_suite(): diff --git a/unittests/text_reader_tester.py b/unittests/text_reader_tester.py index a81d213b..6105dc3c 100644 --- a/unittests/text_reader_tester.py +++ b/unittests/text_reader_tester.py @@ -27,7 +27,7 @@ def test(self): var_i = declarations.find_declaration( decls, type=declarations.variable_t, name='i') - self.failUnless(var_i, "Variable i has not been found.") + self.assertTrue(var_i, "Variable i has not been found.") def create_suite(): diff --git a/unittests/type_as_exception_bug_tester.py b/unittests/type_as_exception_bug_tester.py index ad11ae3e..0784dddf 100644 --- a/unittests/type_as_exception_bug_tester.py +++ b/unittests/type_as_exception_bug_tester.py @@ -26,12 +26,12 @@ def setUp(self): def test(self): buggy = self.global_ns.mem_fun('buggy') ExpressionError = self.global_ns.class_('ExpressionError') - self.failUnless(len(buggy.exceptions) == 1) + self.assertTrue(len(buggy.exceptions) == 1) err = buggy.exceptions[0] - self.failUnless(declarations.is_reference(err)) + self.assertTrue(declarations.is_reference(err)) err = declarations.remove_declarated( declarations.remove_reference(err)) - self.failUnless(err is ExpressionError) + self.assertTrue(err is ExpressionError) def create_suite(): diff --git a/unittests/type_traits_tester.py b/unittests/type_traits_tester.py index 0093f58a..1c085dec 100644 --- a/unittests/type_traits_tester.py +++ b/unittests/type_traits_tester.py @@ -31,28 +31,28 @@ def __test_type_category(self, ns_name, controller): self.declarations, type=declarations.namespace_t, name=ns_name) - self.failUnless(ns_control, "unable to find '%s' namespace" % ns_name) + self.assertTrue(ns_control, "unable to find '%s' namespace" % ns_name) ns_yes = declarations.find_declaration( ns_control, type=declarations.namespace_t, name='yes') - self.failUnless(ns_yes, "unable to find 'yes' namespace") + self.assertTrue(ns_yes, "unable to find 'yes' namespace") ns_no = declarations.find_declaration( ns_control, type=declarations.namespace_t, name='no') - self.failUnless(ns_no, "unable to find 'no' namespace") + self.assertTrue(ns_no, "unable to find 'no' namespace") er = 'for type "%s" the answer to the question "%s" should be True' for decl in ns_yes.declarations: if isinstance(decl, declarations.variable_t): - self.failUnless( + self.assertTrue( controller(decl.type), er % (decl.type.decl_string, ns_name)) elif isinstance(decl, declarations.calldef_t) and \ decl.name.startswith('test_'): continue else: - self.failUnless( + self.assertTrue( controller(decl), er % (decl.decl_string, ns_name)) er = 'for type "%s" the answer to the question "%s" should be False' for decl in ns_no.declarations: @@ -67,28 +67,28 @@ def __test_type_transformation(self, ns_name, transformer): self.declarations, type=declarations.namespace_t, name=ns_name) - self.failUnless(ns_control, "unable to find '%s' namespace" % ns_name) + self.assertTrue(ns_control, "unable to find '%s' namespace" % ns_name) ns_before = declarations.find_declaration( ns_control, type=declarations.namespace_t, name='before') - self.failUnless(ns_before, "unable to find 'before' namespace") + self.assertTrue(ns_before, "unable to find 'before' namespace") ns_after = declarations.find_declaration( ns_control, type=declarations.namespace_t, name='after') - self.failUnless(ns_after, "unable to find 'after' namespace") + self.assertTrue(ns_after, "unable to find 'after' namespace") for tbefore in ns_before.declarations: tafter = declarations.find_declaration( ns_after, name=tbefore.name) - self.failUnless( + self.assertTrue( tafter, "unable to find transformed type definition for type '%s'" % tbefore.decl_string) transformed = transformer(tbefore) - self.failUnless( + self.assertTrue( declarations.is_same( transformed, tafter), @@ -179,7 +179,7 @@ def test_is_base_and_derived(self): self.declarations, type=declarations.namespace_t, name='is_base_and_derived') - self.failUnless(ns, "unable to find 'is_base_and_derived' namespace") + self.assertTrue(ns, "unable to find 'is_base_and_derived' namespace") base = declarations.find_declaration( ns.declarations, type=declarations.class_t, @@ -188,11 +188,11 @@ def test_is_base_and_derived(self): ns.declarations, type=declarations.class_t, name='derived') - self.failUnless( + self.assertTrue( base and derived and declarations.is_base_and_derived( base, derived)) - self.failUnless( + self.assertTrue( base and derived and declarations.is_base_and_derived(base, (derived, derived))) @@ -205,13 +205,13 @@ def test_is_base_and_derived(self): ns.declarations, type=declarations.class_t, name='unrelated2') - self.failUnless( + self.assertTrue( base and derived and not declarations.is_base_and_derived( unrelated1, unrelated2)) def test_is_same(self): - self.failUnless( + self.assertTrue( declarations.is_same( declarations.int_t, declarations.int_t)) @@ -248,11 +248,11 @@ def test_is_unary_binary_operator(self): self.declarations, type=declarations.operator_t, fullname='::is_unary_operator::dummy::operator!') - self.failUnless(operator_not, 'operator! was not found') - self.failUnless( + self.assertTrue(operator_not, 'operator! was not found') + self.assertTrue( declarations.is_unary_operator(operator_not), 'operator! should be idenitified as unary operator') - self.failUnless( + self.assertTrue( not declarations.is_binary_operator(operator_not), 'operator! should be idenitified as unary operator') @@ -260,11 +260,11 @@ def test_is_unary_binary_operator(self): self.declarations, type=declarations.operator_t, fullname='::is_unary_operator::dummy::operator+') - self.failUnless(operator_class_p, 'operator+ was not found') - self.failUnless( + self.assertTrue(operator_class_p, 'operator+ was not found') + self.assertTrue( not declarations.is_unary_operator(operator_class_p), 'operator+ should be idenitified as binary operator') - self.failUnless( + self.assertTrue( declarations.is_binary_operator(operator_class_p), 'operator! should be idenitified as binary operator') @@ -272,11 +272,11 @@ def test_is_unary_binary_operator(self): self.declarations, type=declarations.operator_t, fullname='::is_unary_operator::dummy::operator++') - self.failUnless(operator_class_pp, 'operator++ was not found') - self.failUnless( + self.assertTrue(operator_class_pp, 'operator++ was not found') + self.assertTrue( declarations.is_unary_operator(operator_class_pp), 'operator++ should be idenitified as unary operator') - self.failUnless( + self.assertTrue( not declarations.is_binary_operator(operator_class_pp), 'operator++ should be idenitified as unary operator') @@ -284,11 +284,11 @@ def test_is_unary_binary_operator(self): self.declarations, type=declarations.operator_t, fullname='::is_unary_operator::operator++') - self.failUnless(operator_pp, 'operator++ was not found') - self.failUnless( + self.assertTrue(operator_pp, 'operator++ was not found') + self.assertTrue( declarations.is_unary_operator(operator_pp), 'operator++ should be idenitified as unary operator') - self.failUnless( + self.assertTrue( not declarations.is_binary_operator(operator_pp), 'operator++ should be idenitified as unary operator') @@ -296,11 +296,11 @@ def test_is_unary_binary_operator(self): self.declarations, type=declarations.operator_t, fullname='::is_unary_operator::operator*') - self.failUnless(operator_mm, 'operator-- was not found') - self.failUnless( + self.assertTrue(operator_mm, 'operator-- was not found') + self.assertTrue( not declarations.is_unary_operator(operator_mm), 'operator-- should be idenitified as binary operator') - self.failUnless( + self.assertTrue( declarations.is_binary_operator(operator_mm), 'operator-- should be idenitified as binray operator') @@ -308,11 +308,11 @@ def test_is_unary_binary_operator(self): self.declarations, type=declarations.operator_t, fullname='::is_unary_operator::operator+=') - self.failUnless(operator_pe, 'operator+= was not found') - self.failUnless( + self.assertTrue(operator_pe, 'operator+= was not found') + self.assertTrue( not declarations.is_unary_operator(operator_pe), 'operator+= should be idenitified as binary operator') - self.failUnless( + self.assertTrue( declarations.is_binary_operator(operator_pe), 'operator+= should be idenitified as binray operator') @@ -325,7 +325,7 @@ def __is_convertible_impl(self, decl): name='expected', type=declarations.enumeration_t) expected_value = bool(expected_type.get_name2value_dict()['value']) - self.failUnless( + self.assertTrue( expected_value == declarations.is_convertible( source_type, target_type), @@ -338,7 +338,7 @@ def test_is_convertible(self): type=declarations.namespace_t, name="is_convertible") - self.failUnless( + self.assertTrue( ns_is_convertible, "namespace is_convertible was not found") for tester in [ @@ -360,10 +360,10 @@ def test(self): ci = global_ns.class_('const_item') if 'CastXML' in utils.xml_generator: # Constructor, copy constructor, destructor, variable - self.failUnless(len(ci.declarations) == 4) + self.assertTrue(len(ci.declarations) == 4) else: # Copy constructor, destructor, variable - self.failUnless(len(ci.declarations) == 3) + self.assertTrue(len(ci.declarations) == 3) # class tester_diff_t( parser_test_case.parser_test_case_t ): # COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE @@ -427,7 +427,7 @@ def test_get_declaration(self): declarations.class_traits.get_declaration(easy) deasy = global_ns.typedef('Deasy') d_a = declarations.class_traits.get_declaration(deasy) - self.failUnless(isinstance(d_a, declarations.class_types)) + self.assertTrue(isinstance(d_a, declarations.class_types)) def create_suite(): diff --git a/unittests/typedefs_tester.py b/unittests/typedefs_tester.py index ed2ca2f9..6904faee 100644 --- a/unittests/typedefs_tester.py +++ b/unittests/typedefs_tester.py @@ -30,9 +30,9 @@ def setUp(self): def test(self): item_cls = self.global_ns.class_(name='item_t') - self.failUnless(item_cls, "unable to find class 'item_t'") - self.failUnless(len(item_cls.aliases) == 1) - self.failUnless(item_cls.aliases[0].name == 'Item') + self.assertTrue(item_cls, "unable to find class 'item_t'") + self.assertTrue(len(item_cls.aliases) == 1) + self.assertTrue(item_cls.aliases[0].name == 'Item') class tester_prj_t(parser_test_case.parser_test_case_t): @@ -56,11 +56,11 @@ def test(self): self.declarations, type=declarations.class_t, name='item_t') - self.failUnless(item_cls, "unable to find class 'item_t'") - self.failUnless(len(item_cls.aliases) == 3) + self.assertTrue(item_cls, "unable to find class 'item_t'") + self.assertTrue(len(item_cls.aliases) == 3) expected_aliases = set(['Item', 'Item1', 'Item2']) real_aliases = set([typedef.name for typedef in item_cls.aliases]) - self.failUnless(real_aliases == expected_aliases) + self.assertTrue(real_aliases == expected_aliases) def create_suite(): diff --git a/unittests/undname_creator_tester.py b/unittests/undname_creator_tester.py index 2d2bf171..9e2c6c0e 100644 --- a/unittests/undname_creator_tester.py +++ b/unittests/undname_creator_tester.py @@ -122,12 +122,12 @@ def __tester_impl(self, fname, expected_symbols): symbols, parser = binary_parsers.merge_information( self.global_ns, fname, runs_under_unittest=True) # this doesn't work reliably - # self.failUnless( + # self.assertTrue( # len(symbols) == expected_symbols, # "The expected symbols number(%d), # is different from the actual one(%d)" # % ( expected_symbols, len(symbols) ) ) - self.failUnless('identity' in symbols) + self.assertTrue('identity' in symbols) msg = [] blob_names = set() @@ -179,7 +179,7 @@ def test_z_compare_parsers(self): msymbols, mparser = binary_parsers.merge_information( self.global_ns, self.map_file, runs_under_unittest=True) - self.failUnless( + self.assertTrue( len(dparser.loaded_symbols) == len(mparser.loaded_symbols)) was_error = False @@ -189,12 +189,12 @@ def test_z_compare_parsers(self): print( '\n%s could not be found in .map file' % binary_parsers.undecorate_blob(blob)) - # self.failUnless( blob in msymbols, + # self.assertTrue( blob in msymbols, # binary_parsers.undecorate_blob( blob ) ) else: mdecl = msymbols[blob] - self.failUnless(mdecl is decl) - self.failUnless(was_error is False) + self.assertTrue(mdecl is decl) + self.assertTrue(was_error is False) def test_so_file(self): if 'posix' in os.name: diff --git a/unittests/unnamed_classes_tester.py b/unittests/unnamed_classes_tester.py index 760f4a19..cc2fd5f3 100644 --- a/unittests/unnamed_classes_tester.py +++ b/unittests/unnamed_classes_tester.py @@ -25,7 +25,7 @@ def setUp(self): def test(self): # bf_x = self.global_ns.variable( 'x' ) - # self.failUnless( bf_x.bits == 1 ) + # self.assertTrue( bf_x.bits == 1 ) pass diff --git a/unittests/unnamed_enums_bug_tester.py b/unittests/unnamed_enums_bug_tester.py index 0fe830d1..23f66c9d 100644 --- a/unittests/unnamed_enums_bug_tester.py +++ b/unittests/unnamed_enums_bug_tester.py @@ -29,11 +29,11 @@ def test(self): enums = self.global_ns.enums() for enum in enums: names.extend(list(enum.get_name2value_dict().keys())) - self.failUnless(len(names) == 4) - self.failUnless('x1' in names) - self.failUnless('x2' in names) - self.failUnless('y1' in names) - self.failUnless('y2' in names) + self.assertTrue(len(names) == 4) + self.assertTrue('x1' in names) + self.assertTrue('x2' in names) + self.assertTrue('y1' in names) + self.assertTrue('y2' in names) class project_reader_1_tester_t(parser_test_case.parser_test_case_t): @@ -53,11 +53,11 @@ def test(self): names = [] for enum in self.global_ns.enums(): names.extend(list(enum.get_name2value_dict().keys())) - self.failUnless(len(names) == 4) - self.failUnless('x1' in names) - self.failUnless('x2' in names) - self.failUnless('y1' in names) - self.failUnless('y2' in names) + self.assertTrue(len(names) == 4) + self.assertTrue('x1' in names) + self.assertTrue('x2' in names) + self.assertTrue('y1' in names) + self.assertTrue('y2' in names) class project_reader_3_tester_t(parser_test_case.parser_test_case_t): @@ -82,13 +82,13 @@ def test(self): list(map( lambda enum: names.extend(list(enum.get_name2value_dict().keys())), enums)) - self.failUnless(len(names) == 6) - self.failUnless('x1' in names) - self.failUnless('x2' in names) - self.failUnless('y1' in names) - self.failUnless('y2' in names) - self.failUnless('z1' in names) - self.failUnless('z2' in names) + self.assertTrue(len(names) == 6) + self.assertTrue('x1' in names) + self.assertTrue('x2' in names) + self.assertTrue('y1' in names) + self.assertTrue('y2' in names) + self.assertTrue('z1' in names) + self.assertTrue('z2' in names) def create_suite(): diff --git a/unittests/variable_matcher_tester.py b/unittests/variable_matcher_tester.py index 410f5456..1f9cfb4b 100644 --- a/unittests/variable_matcher_tester.py +++ b/unittests/variable_matcher_tester.py @@ -32,7 +32,7 @@ def test(self): comp_str = ( '(decl type==variable_t) and (name==x) and ' + '(value type==unsigned int)') - self.failUnless(str(criteria) == comp_str) + self.assertTrue(str(criteria) == comp_str) criteria = declarations.variable_matcher_t( name='::bit_fields::fields_t::x', @@ -42,9 +42,9 @@ def test(self): header_file=x.location.file_name) x = declarations.matcher.get_single(criteria, self.declarations) - self.failUnless(x, "Variable was not found.") + self.assertTrue(x, "Variable was not found.") - self.failUnless('public' == x.access_type) + self.assertTrue('public' == x.access_type) class tester_2_t(parser_test_case.parser_test_case_t): diff --git a/unittests/vector_traits_tester.py b/unittests/vector_traits_tester.py index 2ca12a84..28d3b8c3 100644 --- a/unittests/vector_traits_tester.py +++ b/unittests/vector_traits_tester.py @@ -26,12 +26,12 @@ def setUp(self): def validate_yes(self, value_type, container): traits = declarations.vector_traits - self.failUnless(traits.is_my_case(container)) - self.failUnless( + self.assertTrue(traits.is_my_case(container)) + self.assertTrue( declarations.is_same( value_type, traits.element_type(container))) - self.failUnless(traits.is_sequence(container)) + self.assertTrue(traits.is_sequence(container)) def test_global_ns(self): value_type = self.global_ns.class_('_0_') @@ -57,7 +57,7 @@ def test_no(self): continue if not struct.name.endswith('_'): continue - self.failUnless(not traits.is_my_case(struct.typedef('container'))) + self.assertTrue(not traits.is_my_case(struct.typedef('container'))) def test_declaration(self): cnt = ( @@ -68,7 +68,7 @@ def test_declaration(self): 'std::allocator >,std::allocator, std::allocator > > >') traits = declarations.find_container_traits(cnt) - self.failUnless(declarations.vector_traits is traits) + self.assertTrue(declarations.vector_traits is traits) def test_element_type(self): do_nothing = self.global_ns.free_fun('do_nothing') From 91f4f0e1f2dfdaff06c79f298d42191f1f3248af Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 Nov 2015 23:19:36 +0100 Subject: [PATCH 028/268] Remove even more b modes for files --- unittests/file_cache_tester.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unittests/file_cache_tester.py b/unittests/file_cache_tester.py index 3ab3603f..8fd74d01 100644 --- a/unittests/file_cache_tester.py +++ b/unittests/file_cache_tester.py @@ -24,13 +24,13 @@ def __init__(self, *args): def touch(self): # Need to change file. - with open(self.header, "ab+") as header: + with open(self.header, "a+") as header: header.write("//touch") def test_update(self): # Save the content of the header file for later - with open(self.header, "rb") as old_header: + with open(self.header, "r") as old_header: content = old_header.read() declarations = parser.parse([self.header], self.config) From 6e53b10b29d9067bc331eaccae88b3ad015afed8 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 Nov 2015 23:27:21 +0100 Subject: [PATCH 029/268] Use assertRaises --- unittests/declaration_matcher_tester.py | 4 ++-- unittests/gccxml_runner_tester.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/unittests/declaration_matcher_tester.py b/unittests/declaration_matcher_tester.py index dd14af75..2f16e14a 100644 --- a/unittests/declaration_matcher_tester.py +++ b/unittests/declaration_matcher_tester.py @@ -36,10 +36,10 @@ def test_ns1(self): ns1 = gns.namespace('ns') gns.class_('nested_cls') - self.assertTrueRaises(Exception, lambda: gns.class_('ns::nested_cls')) + self.assertRaises(Exception, lambda: gns.class_('ns::nested_cls')) gns.class_('::ns::nested_cls') - self.assertTrueRaises(Exception, lambda: ns1.class_('::nested_cls')) + self.assertRaises(Exception, lambda: ns1.class_('::nested_cls')) ns1.class_('nested_cls') ns1.class_('::ns::nested_cls') diff --git a/unittests/gccxml_runner_tester.py b/unittests/gccxml_runner_tester.py index f6924dcb..18bad4b3 100644 --- a/unittests/gccxml_runner_tester.py +++ b/unittests/gccxml_runner_tester.py @@ -17,7 +17,7 @@ def __init__(self, *args): self.content = "abra cadabra " + os.linesep def test_gccxml_on_input_with_errors(self): - self.assertTrueRaises( + self.assertRaises( RuntimeError, parser.parse_string, self.content, From dc9f29b1b65260bc821084c98d3e1a8f8205d42b Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 14 Nov 2015 23:42:51 +0100 Subject: [PATCH 030/268] Use new-style Python classes --- pygccxml/binary_parsers/undname.py | 4 ++-- pygccxml/declarations/algorithm.py | 2 +- pygccxml/declarations/calldef.py | 4 ++-- pygccxml/declarations/class_declaration.py | 4 ++-- pygccxml/declarations/type_traits.py | 12 ++++++------ pygccxml/parser/directory_cache.py | 6 +++--- pygccxml/parser/project_reader.py | 6 +++--- pygccxml/parser/source_reader.py | 2 +- pygccxml/utils/utils.py | 2 +- unittests/autoconfig.py | 2 +- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/pygccxml/binary_parsers/undname.py b/pygccxml/binary_parsers/undname.py index 6e9a1b33..128f3178 100644 --- a/pygccxml/binary_parsers/undname.py +++ b/pygccxml/binary_parsers/undname.py @@ -21,7 +21,7 @@ from .. import declarations -class UNDECORATE_NAME_OPTIONS: +class UNDECORATE_NAME_OPTIONS(object): """defines few constants for `UnDecorateSymbolName` function""" @@ -76,7 +76,7 @@ class UNDECORATE_NAME_OPTIONS: | UNDNAME_NO_ACCESS_SPECIFIERS | UNDNAME_NO_ECSU -class undname_creator_t: +class undname_creator_t(object): """implementation details - should not be used directly diff --git a/pygccxml/declarations/algorithm.py b/pygccxml/declarations/algorithm.py index a908ebfd..a42d7ce5 100644 --- a/pygccxml/declarations/algorithm.py +++ b/pygccxml/declarations/algorithm.py @@ -213,7 +213,7 @@ def get_global_namespace(decls): raise RuntimeError("Unable to find global namespace.") -class match_declaration_t: +class match_declaration_t(object): """ Helper class for different search algorithms. diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index aae095fc..a029e876 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -26,7 +26,7 @@ from .. import utils -class VIRTUALITY_TYPES: +class VIRTUALITY_TYPES(object): """class that defines "virtuality" constants""" NOT_VIRTUAL = 'not virtual' @@ -37,7 +37,7 @@ class VIRTUALITY_TYPES: FUNCTION_VIRTUALITY_TYPES = VIRTUALITY_TYPES -class CALLING_CONVENTION_TYPES: +class CALLING_CONVENTION_TYPES(object): """class that defines "calling convention" constants""" UNKNOWN = '' diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 46843f13..1d9f01c4 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -19,7 +19,7 @@ from pygccxml import utils -class ACCESS_TYPES: +class ACCESS_TYPES(object): """class that defines "access" constants""" PUBLIC = "public" @@ -28,7 +28,7 @@ class ACCESS_TYPES: ALL = [PUBLIC, PRIVATE, PROTECTED] -class CLASS_TYPES: +class CLASS_TYPES(object): """class that defines "class" type constants""" CLASS = "class" diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index be605486..0d60f664 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -365,7 +365,7 @@ def is_fundamental(type): (cpptypes.volatile_t, cpptypes.const_t)) -class declaration_xxx_traits: +class declaration_xxx_traits(object): """this class implements the functionality needed for convenient work with declaration classes @@ -634,7 +634,7 @@ def is_binary_operator(oper): return False -class __is_convertible_t: +class __is_convertible_t(object): """implementation details""" @@ -1056,7 +1056,7 @@ def is_defined_in_xxx(xxx, cls): return None is global_ns.parent -class impl_details: +class impl_details(object): """implementation details""" @staticmethod @@ -1133,7 +1133,7 @@ def find_value_type(global_ns, value_type_str): return None -class internal_type_traits: +class internal_type_traits(object): """small convenience class, which provides access to internal types""" # TODO: add exists function @@ -1158,7 +1158,7 @@ def get_by_name(type_, name): % (name, type_.decl_string)) -class smart_pointer_traits: +class smart_pointer_traits(object): """implements functionality, needed for convenient work with smart pointers""" @@ -1188,7 +1188,7 @@ def value_type(type_): return internal_type_traits.get_by_name(type_, "value_type") -class auto_ptr_traits: +class auto_ptr_traits(object): """implements functionality, needed for convenient work with `std::auto_ptr` pointers""" diff --git a/pygccxml/parser/directory_cache.py b/pygccxml/parser/directory_cache.py index 1924f9cb..e6497423 100644 --- a/pygccxml/parser/directory_cache.py +++ b/pygccxml/parser/directory_cache.py @@ -27,7 +27,7 @@ from . import declarations_cache -class index_entry_t: +class index_entry_t(object): """ Entry of the index table in the directory cache index. @@ -376,7 +376,7 @@ def _create_config_signature(self, config): return m.digest() -class filename_entry_t: +class filename_entry_t(object): """This is a record stored in the filename_repository_t class. @@ -423,7 +423,7 @@ def dec_ref_count(self): return self.refcount -class filename_repository_t: +class filename_repository_t(object): """File name repository. diff --git a/pygccxml/parser/project_reader.py b/pygccxml/parser/project_reader.py index 6e619c85..f75ffd55 100644 --- a/pygccxml/parser/project_reader.py +++ b/pygccxml/parser/project_reader.py @@ -11,7 +11,7 @@ from .. import utils -class COMPILATION_MODE: +class COMPILATION_MODE(object): ALL_AT_ONCE = 'all at once' FILE_BY_FILE = 'file by file' @@ -53,7 +53,7 @@ class file_configuration_t(object): """ - class CONTENT_TYPE: + class CONTENT_TYPE(object): STANDARD_SOURCE_FILE = 'standard source file' CACHED_SOURCE_FILE = 'cached source file' GCCXML_GENERATED_FILE = 'gccxml generated file' @@ -163,7 +163,7 @@ def create_cached_source_fc(header, cached_source_file): content_type=file_configuration_t.CONTENT_TYPE.CACHED_SOURCE_FILE) -class project_reader_t: +class project_reader_t(object): """parses header files and returns the contained declarations""" diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 508bb6bc..158257c1 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -48,7 +48,7 @@ def bind_aliases(decls): cls_inst.aliases.append(decl) -class source_reader_t: +class source_reader_t(object): """ This class reads C++ source code and returns the declarations tree. diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index 469d0878..0d7c92be 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -300,7 +300,7 @@ def name_of(cls, enum_numeric_value): (enum_numeric_value, cls.__name__)) -class native_compiler: +class native_compiler(object): """ Provides information about the compiler which was used to build the Python executable diff --git a/unittests/autoconfig.py b/unittests/autoconfig.py index afe5ccc7..ebee2175 100644 --- a/unittests/autoconfig.py +++ b/unittests/autoconfig.py @@ -32,7 +32,7 @@ pygccxml.declarations.class_t.USE_DEMANGLED_AS_NAME = True -class cxx_parsers_cfg: +class cxx_parsers_cfg(object): gccxml = pygccxml.parser.load_xml_generator_configuration( 'xml_generator.cfg', xml_generator_path=generator_path, From d499d55ab629e8139771f21e94c4b00902525ee9 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 15 Nov 2015 12:05:02 +0100 Subject: [PATCH 031/268] Avoid using `len(x)` to check if x is empty --- pygccxml/declarations/enumeration.py | 2 +- pygccxml/declarations/matcher.py | 2 +- pygccxml/parser/directory_cache.py | 2 +- pygccxml/parser/source_reader.py | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pygccxml/declarations/enumeration.py b/pygccxml/declarations/enumeration.py index fab0ec94..841ad890 100644 --- a/pygccxml/declarations/enumeration.py +++ b/pygccxml/declarations/enumeration.py @@ -101,7 +101,7 @@ def append_value(self, valuename, valuenum=None): """ # No number given? Then use the previous one + 1 if valuenum is None: - if len(self._values) == 0: + if not self._values: valuenum = 0 else: valuenum = self._values[-1][1] + 1 diff --git a/pygccxml/declarations/matcher.py b/pygccxml/declarations/matcher.py index 32142961..1cf84f24 100644 --- a/pygccxml/declarations/matcher.py +++ b/pygccxml/declarations/matcher.py @@ -102,7 +102,7 @@ def get_single(decl_matcher, decls, recursive=True): answer = matcher.find(decl_matcher, decls, recursive) if len(answer) == 1: return answer[0] - elif len(answer) == 0: + elif not answer: raise matcher.declaration_not_found_t(decl_matcher) else: raise matcher.multiple_declarations_found_t(decl_matcher) diff --git a/pygccxml/parser/directory_cache.py b/pygccxml/parser/directory_cache.py index e6497423..6bf2d04c 100644 --- a/pygccxml/parser/directory_cache.py +++ b/pygccxml/parser/directory_cache.py @@ -515,7 +515,7 @@ def update_id_counter(self): """Update the `id_` counter so that it doesn't grow forever. """ - if len(self.__entries) == 0: + if not self.__entries: self.__next_id = 1 else: self.__next_id = max(self.__entries.keys()) + 1 diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 158257c1..93713f58 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -227,11 +227,12 @@ def __add_symbols(self, cmd): """ - if len(self.__config.define_symbols) != 0: + if self.__config.define_symbols: symbols = self.__config.define_symbols cmd.append(''.join( [' -D"%s"' % defined_symbol for defined_symbol in symbols])) - if len(self.__config.undefine_symbols) != 0: + + if self.__config.undefine_symbols: un_symbols = self.__config.undefine_symbols cmd.append( ''.join([' -U"%s"' % undefined_symbol for From 2f934ccd2d12d3dc49eb4c62430f3d8fb0d49c14 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 15 Nov 2015 12:08:48 +0100 Subject: [PATCH 032/268] Use new-style Python class --- pygccxml/declarations/matcher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygccxml/declarations/matcher.py b/pygccxml/declarations/matcher.py index 1cf84f24..91b220d9 100644 --- a/pygccxml/declarations/matcher.py +++ b/pygccxml/declarations/matcher.py @@ -8,7 +8,7 @@ from . import algorithm -class matcher: +class matcher(object): """Class-namespace, contains implementation of a few "find" algorithms and definition of the related exception classes""" From 666c0fe8ea5c67c6a0392c5973b303798ea39c1a Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 16 Nov 2015 23:53:55 +0100 Subject: [PATCH 033/268] Add option to remove the __va_list_tag declaration from the tree when parsing with CastXML This option is on by default. The __va_list_tag declarations are internal declarations, which are probably not needed. They are for example polluting the declarations tree when running pyplusplus. The removal can still be re-enabled by setting the utils.remove__va_list_tag option to False. This fixes also the filter test, which has now the correct initial number of declarations (the same as for gccxml). It also removes the hack in the hierarchy_travelling test. --- pygccxml/parser/scanner.py | 17 +++++++++++++++++ pygccxml/utils/__init__.py | 4 ++++ unittests/filters_tester.py | 10 ++-------- unittests/hierarchy_traveling.py | 11 ----------- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index 15fda47d..9e34c053 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -201,7 +201,17 @@ def startElement(self, name, attrs): self.__inst = obj self.__read_access(attrs) element_id = attrs.get(XML_AN_ID, None) + + # With CastXML and clang some __va_list_tag declarations are + # present in the tree: we do not want to have these in the tree. + # This option is set to True by default + remove_va_list_tag = utils.remove__va_list_tag + if isinstance(obj, declarations.declaration_t): + + if remove_va_list_tag and "__va_list_tag" in str(obj.name): + return + # XML generator. Kept for retrocompatibily obj.compiler = utils.xml_generator @@ -217,11 +227,18 @@ def startElement(self, name, attrs): self.__read_attributes(obj, attrs) elif isinstance(obj, declarations.type_t): + self.__types[element_id] = obj self.__read_byte_size(obj, attrs) self.__read_byte_align(obj, attrs) + elif utils.is_str(obj): + + if remove_va_list_tag and "__va_list_tag" in obj: + return + self.__files[element_id] = obj + else: self.logger.warning( 'Unknown object type has been found.' + diff --git a/pygccxml/utils/__init__.py b/pygccxml/utils/__init__.py index 6fc4c23a..7ce3d13f 100644 --- a/pygccxml/utils/__init__.py +++ b/pygccxml/utils/__init__.py @@ -20,3 +20,7 @@ # Version of xml generator which was used. xml_generator = None + +# With CastXML and clang some __va_list_tag declarations are present in the +# tree. This options allows to remove them when parsing the xml file. +remove__va_list_tag = True diff --git a/unittests/filters_tester.py b/unittests/filters_tester.py index 92799463..673f1363 100644 --- a/unittests/filters_tester.py +++ b/unittests/filters_tester.py @@ -39,14 +39,8 @@ def test_access_type(self): criteria = declarations.access_type_matcher_t( declarations.ACCESS_TYPES.PUBLIC) public_members = declarations.matcher.find(criteria, self.global_ns) - if "CastXML" in utils.xml_generator: - public_members = [d for d in public_members if not d.is_artificial] - self.assertTrue(21 == len(public_members)) - if "0.9" in utils.xml_generator: - public_members = [d for d in public_members if not d.is_artificial] - self.assertTrue(17 == len(public_members)) - else: - self.assertTrue(21 == len(public_members)) + public_members = [d for d in public_members if not d.is_artificial] + self.assertTrue(17 == len(public_members)) def test_or_matcher(self): criteria1 = declarations.regex_matcher_t( diff --git a/unittests/hierarchy_traveling.py b/unittests/hierarchy_traveling.py index 74c7aa20..2c37c0e9 100644 --- a/unittests/hierarchy_traveling.py +++ b/unittests/hierarchy_traveling.py @@ -9,7 +9,6 @@ from pygccxml import parser from pygccxml import declarations -from pygccxml import utils class tester_t(parser_test_case.parser_test_case_t): @@ -53,11 +52,6 @@ def test_recursive_bases(self): classes = [ inst for inst in decls if isinstance(inst, declarations.class_t)] for class_ in classes: - if "CastXML" in utils.xml_generator and \ - class_.name == "__va_list_tag": - # With CastXML; there is a __va_list_tag which is generated by - # clang. Do not run the tests for it. - continue self.assertTrue(class_.name in self.__recursive_bases) all_bases = class_.recursive_bases control_bases = self.__recursive_bases[class_.name] @@ -73,11 +67,6 @@ def test_recursive_derived(self): inst, declarations.class_t)] for class_ in classes: - if "CastXML" in utils.xml_generator and \ - class_.name == "__va_list_tag": - # With CastXML; there is a __va_list_tag which is generated by - # clang. Do not run the tests for it. - continue self.assertTrue(class_.name in self.__recursive_derived) all_derived = class_.recursive_derived control_derived = self.__recursive_derived[class_.name] From fca72983332ece4623db187e1c074190bb2b68f2 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 17 Nov 2015 00:09:06 +0100 Subject: [PATCH 034/268] Add test for the __va_list_tag removal --- unittests/test_all.py | 4 +- unittests/test_va_list_tag_removal.py | 94 +++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 unittests/test_va_list_tag_removal.py diff --git a/unittests/test_all.py b/unittests/test_all.py index 2cc21a37..29ba536f 100644 --- a/unittests/test_all.py +++ b/unittests/test_all.py @@ -66,6 +66,7 @@ import pep8_tester import example_tester import test_utils +import test_va_list_tag_removal testers = [ # , demangled_tester # failing right now @@ -124,7 +125,8 @@ from_future_import_tester, pep8_tester, example_tester, - test_utils + test_utils, + test_va_list_tag_removal ] if 'posix' in os.name: diff --git a/unittests/test_va_list_tag_removal.py b/unittests/test_va_list_tag_removal.py new file mode 100644 index 00000000..f3cf2a13 --- /dev/null +++ b/unittests/test_va_list_tag_removal.py @@ -0,0 +1,94 @@ +# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +import os +import unittest +import parser_test_case + +from pygccxml import parser +from pygccxml import declarations +from pygccxml import utils + + +class tester_t(parser_test_case.parser_test_case_t): + + """ + Test the remove__va_list_tag option + + With CastXML and clang some __va_list_tag declarations are present in the + tree. This options allows to remove them when parsing the xml file. + + """ + + def __init__(self, *args): + parser_test_case.parser_test_case_t.__init__(self, *args) + self.__code = os.linesep.join(['struct a{};']) + + def test_keep_va_list_tag(self): + utils.remove__va_list_tag = False + src_reader = parser.source_reader_t(self.config) + decls = declarations.make_flatten(src_reader.read_string(self.__code)) + + classes = [ + i for i in decls if isinstance(i, declarations.class_t)] + + typedefs = [ + i for i in decls if isinstance(i, declarations.typedef_t)] + + variables = [ + i for i in decls if isinstance(i, declarations.variable_t)] + + tag = "__va_list_tag" + + self.assertTrue(tag in [class_.name for class_ in classes]) + self.assertTrue("a" in [class_.name for class_ in classes]) + self.assertTrue(len(classes) == 2) + + self.assertTrue(tag in [ty.name for ty in typedefs]) + self.assertTrue(len(typedefs) == 4) + + self.assertTrue( + tag in [var.decl_string.split("::")[1] for var in variables]) + self.assertTrue(len(variables) == 4) + + def test_remove_va_list_tag(self): + utils.remove__va_list_tag = True + src_reader = parser.source_reader_t(self.config) + decls = declarations.make_flatten(src_reader.read_string(self.__code)) + + classes = [ + i for i in decls if isinstance(i, declarations.class_t)] + + typedefs = [ + i for i in decls if isinstance(i, declarations.typedef_t)] + + variables = [ + i for i in decls if isinstance(i, declarations.variable_t)] + + tag = "__va_list_tag" + + self.assertFalse(tag in [class_.name for class_ in classes]) + self.assertTrue("a" in [class_.name for class_ in classes]) + self.assertTrue(len(classes) == 1) + + self.assertFalse(tag in [ty.name for ty in typedefs]) + self.assertTrue(len(typedefs) == 3) + + self.assertFalse( + tag in [var.decl_string.split("::")[1] for var in variables]) + self.assertTrue(len(variables) == 0) + + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(tester_t)) + return suite + + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run(create_suite()) + +if __name__ == "__main__": + run_suite() From 2dafefa9ccee91309d5049aa931e35df120433b9 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 17 Nov 2015 19:14:11 +0100 Subject: [PATCH 035/268] Do not run the __va_list_tag with gccxml --- unittests/test_va_list_tag_removal.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/unittests/test_va_list_tag_removal.py b/unittests/test_va_list_tag_removal.py index f3cf2a13..a2050d44 100644 --- a/unittests/test_va_list_tag_removal.py +++ b/unittests/test_va_list_tag_removal.py @@ -27,6 +27,10 @@ def __init__(self, *args): self.__code = os.linesep.join(['struct a{};']) def test_keep_va_list_tag(self): + + if "GCCXML" in self.config.xml_generator: + return True + utils.remove__va_list_tag = False src_reader = parser.source_reader_t(self.config) decls = declarations.make_flatten(src_reader.read_string(self.__code)) @@ -54,6 +58,10 @@ def test_keep_va_list_tag(self): self.assertTrue(len(variables) == 4) def test_remove_va_list_tag(self): + + if "GCCXML" in self.config.xml_generator: + return True + utils.remove__va_list_tag = True src_reader = parser.source_reader_t(self.config) decls = declarations.make_flatten(src_reader.read_string(self.__code)) From c0fe8258a1c0e5be90308f99740009809515f68c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 17 Nov 2015 19:38:08 +0100 Subject: [PATCH 036/268] Introduce a way to passe flags to the config and use it This will allow to enable/disable stuff in the future. The f1 flag, when set, will add the __va_list_tag declarations to the tree. By default the flag is not set. --- pygccxml/parser/config.py | 27 ++++++++++++++++++++++++--- pygccxml/parser/scanner.py | 2 +- pygccxml/utils/__init__.py | 4 ---- unittests/test_va_list_tag_removal.py | 4 ++-- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index 75ea005a..4730d619 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -43,7 +43,8 @@ def __init__( compiler=None, xml_generator="gccxml", keep_xml=False, - compiler_path=None): + compiler_path=None, + flags=None): object.__init__(self) self.__working_directory = working_directory @@ -68,6 +69,10 @@ def __init__( self.__keep_xml = keep_xml + if flags is None: + flags = [] + self.__flags = flags + # If no compiler path was set and we are using castxml, set the path self.__compiler_path = create_compiler_path( xml_generator, compiler_path) @@ -128,6 +133,18 @@ def keep_xml(self, keep_xml): """Set if xml files kept after errors.""" self.__keep_xml = keep_xml + @property + def flags(self): + """Optional flags for pygccxml.""" + return self.__flags + + @flags.setter + def flags(self, flags): + """Optional flags for pygccxml.""" + if flags is None: + flags = [] + self.__flags = flags + @property def compiler_path(self): """Get the path for the compiler.""" @@ -192,7 +209,8 @@ def __init__( compiler=None, xml_generator="gccxml", keep_xml=False, - compiler_path=None): + compiler_path=None, + flags=None): parser_configuration_t.__init__( self, @@ -204,7 +222,8 @@ def __init__( compiler=compiler, xml_generator=xml_generator, keep_xml=keep_xml, - compiler_path=compiler_path) + compiler_path=compiler_path, + flags=flags) if gccxml_path != '': self.__gccxml_path = gccxml_path @@ -400,6 +419,8 @@ def load_xml_generator_configuration(configuration, **defaults): cfg.xml_generator = value elif name == 'keep_xml': cfg.keep_xml = value + elif name == 'flags': + cfg.flags = value elif name == 'compiler_path': cfg.compiler_path = value else: diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index 9e34c053..a7b94ccf 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -205,7 +205,7 @@ def startElement(self, name, attrs): # With CastXML and clang some __va_list_tag declarations are # present in the tree: we do not want to have these in the tree. # This option is set to True by default - remove_va_list_tag = utils.remove__va_list_tag + remove_va_list_tag = "f1" not in self.config.flags if isinstance(obj, declarations.declaration_t): diff --git a/pygccxml/utils/__init__.py b/pygccxml/utils/__init__.py index 7ce3d13f..6fc4c23a 100644 --- a/pygccxml/utils/__init__.py +++ b/pygccxml/utils/__init__.py @@ -20,7 +20,3 @@ # Version of xml generator which was used. xml_generator = None - -# With CastXML and clang some __va_list_tag declarations are present in the -# tree. This options allows to remove them when parsing the xml file. -remove__va_list_tag = True diff --git a/unittests/test_va_list_tag_removal.py b/unittests/test_va_list_tag_removal.py index a2050d44..517c5231 100644 --- a/unittests/test_va_list_tag_removal.py +++ b/unittests/test_va_list_tag_removal.py @@ -31,7 +31,7 @@ def test_keep_va_list_tag(self): if "GCCXML" in self.config.xml_generator: return True - utils.remove__va_list_tag = False + self.config.flags = ["f1"] src_reader = parser.source_reader_t(self.config) decls = declarations.make_flatten(src_reader.read_string(self.__code)) @@ -62,7 +62,7 @@ def test_remove_va_list_tag(self): if "GCCXML" in self.config.xml_generator: return True - utils.remove__va_list_tag = True + self.config.flags = [] src_reader = parser.source_reader_t(self.config) decls = declarations.make_flatten(src_reader.read_string(self.__code)) From 7f4abe00e0d0018da1c1aa58d5c1b1c80ba23022 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 17 Nov 2015 20:00:17 +0100 Subject: [PATCH 037/268] Compare against the right xml generator name in test --- unittests/test_va_list_tag_removal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unittests/test_va_list_tag_removal.py b/unittests/test_va_list_tag_removal.py index 517c5231..0fdb7df5 100644 --- a/unittests/test_va_list_tag_removal.py +++ b/unittests/test_va_list_tag_removal.py @@ -28,7 +28,7 @@ def __init__(self, *args): def test_keep_va_list_tag(self): - if "GCCXML" in self.config.xml_generator: + if "gccxml" in self.config.xml_generator: return True self.config.flags = ["f1"] @@ -59,7 +59,7 @@ def test_keep_va_list_tag(self): def test_remove_va_list_tag(self): - if "GCCXML" in self.config.xml_generator: + if "gccxml" in self.config.xml_generator: return True self.config.flags = [] From b17ba803e1e3ae0845334e814c33b9216814f60a Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 19 Nov 2015 22:05:13 +0100 Subject: [PATCH 038/268] Document change for next version --- docs/history.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/history.rst b/docs/history.rst index 0ed970c1..26d595cb 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -11,6 +11,24 @@ to python 3 (keeping it compatible with python 2). In Mai 2014, Michka Popoff and the Insight Software Consortium revived pygccxml by setting up a git repositery on github, hosted along with gccxml. +Version 1.7.1 +------------- + +1. Remove the __va_list_tag declaration from the tree when parsing with CastXML + + The __va_list_tag declarations are internal declarations, which are often + not needed. They are for example polluting the declarations tree when running + pyplusplus. + + This is optional but on by default. To still load the __va_list_tag declarations + in the tree, a config flag can be set like this: ``config.flags = ["f1"]``, + or by passing the ``flags=["f1"]`` argument the config setup. + +2. Some code cleanup + +3. Build new package for pypi. The ``1.7.0`` upload has gone wrong ... + + Version 1.7.0 ------------- From 656c3eac5d1a2527fd0effcad8f9592f99f9d94b Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 19 Nov 2015 22:05:38 +0100 Subject: [PATCH 039/268] Bump to version 1.7.1 --- docs/conf.py | 4 ++-- pygccxml/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index a6a35d55..9c5bb6b1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -53,9 +53,9 @@ # built documents. # # The short X.Y version. -version = 'v1.7.0' +version = 'v1.7.1' # The full version, including alpha/beta/rc tags. -release = 'v1.7.0' +release = 'v1.7.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/pygccxml/__init__.py b/pygccxml/__init__.py index d8a1e9b2..b4dcd451 100644 --- a/pygccxml/__init__.py +++ b/pygccxml/__init__.py @@ -40,4 +40,4 @@ # TODO: # 1. Add "explicit" property for constructors -__version__ = 'v1.7.0' +__version__ = 'v1.7.1' From d8d65f04ea9012e29580f12d59d8df2b9b3f4043 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 19 Nov 2015 22:24:51 +0100 Subject: [PATCH 040/268] Tag version 1.7.1 in setup.py This was forgotten before the tagging .. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9ddd7797..f84f62f0 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ from setuptools import setup setup(name="pygccxml", - version="v1.7.0", + version="v1.7.1", author="Roman Yakovenko", author_email="roman yakovenko at gmail com", maintainer="Michka Popoff and the Insight Software Consortium", From 9f3b924f4893be72c420c74510d8d114b7eec22f Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 24 Nov 2015 22:15:09 +0100 Subject: [PATCH 041/268] Add .pyo files to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 624b27ce..438d00b2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.pyc +*.pyo *~ docs/_build unittests/temp From ea6c2009391cdc0e06ad424be0691750d68a9de9 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 24 Nov 2015 22:35:28 +0100 Subject: [PATCH 042/268] Use an assertRaises in test, remove exception with pass --- unittests/from_future_import_tester.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/unittests/from_future_import_tester.py b/unittests/from_future_import_tester.py index ca4dfc9d..3bb98d82 100644 --- a/unittests/from_future_import_tester.py +++ b/unittests/from_future_import_tester.py @@ -30,12 +30,7 @@ def test_namespace_argument_string(self): def test_namespace_argument_int(self): # Check with an int, should raise an error - try: - # This should fail - self.global_ns.namespace(1) - self.fail("No error message triggered") - except AssertionError: - pass + self.assertRaises(AssertionError, lambda: self.global_ns.namespace(1)) def setUp(self): reader = parser.source_reader_t(self.config) From 671a1bc515addf4d6a4f2a1c52513f57163f2c29 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 28 Nov 2015 11:18:35 +0100 Subject: [PATCH 043/268] Hide copyright mention in the examples --- docs/example/example.hpp.rst | 1 + docs/example/example.py.rst | 1 + docs/examples/caching/example.rst | 2 ++ docs/examples/parsing/example.rst | 2 ++ docs/examples/variables/example.rst | 2 ++ 5 files changed, 8 insertions(+) diff --git a/docs/example/example.hpp.rst b/docs/example/example.hpp.rst index ef678685..45ac945a 100644 --- a/docs/example/example.hpp.rst +++ b/docs/example/example.hpp.rst @@ -4,3 +4,4 @@ C++ header file .. literalinclude:: example.hpp :language: c++ + :lines: 5- diff --git a/docs/example/example.py.rst b/docs/example/example.py.rst index 11f1ab70..1f70e313 100644 --- a/docs/example/example.py.rst +++ b/docs/example/example.py.rst @@ -4,4 +4,5 @@ Python API usage example .. literalinclude:: example.py :language: python + :lines: 5- diff --git a/docs/examples/caching/example.rst b/docs/examples/caching/example.rst index b45093d3..05a4e007 100644 --- a/docs/examples/caching/example.rst +++ b/docs/examples/caching/example.rst @@ -10,11 +10,13 @@ Let's consider the following c++ file: .. literalinclude:: example.hpp :language: c++ + :lines: 4- To enable caching, you can use the following code: .. literalinclude:: example.py :language: python + :lines: 4- The first time you run this example, the c++ file will be read and a xml file will be generated: diff --git a/docs/examples/parsing/example.rst b/docs/examples/parsing/example.rst index 73778afd..d9123a2f 100644 --- a/docs/examples/parsing/example.rst +++ b/docs/examples/parsing/example.rst @@ -9,6 +9,7 @@ Let's consider the following c++ file (example.hpp): .. literalinclude:: example.hpp :language: c++ + :lines: 4- The following code will show you how to create a configuration for the xml generator (an external tool, either castxml or gccxml), @@ -16,3 +17,4 @@ and how to parse the c++ file: .. literalinclude:: example.py :language: python + :lines: 4- diff --git a/docs/examples/variables/example.rst b/docs/examples/variables/example.rst index a0392615..ef437cc4 100644 --- a/docs/examples/variables/example.rst +++ b/docs/examples/variables/example.rst @@ -8,9 +8,11 @@ Let's consider the following c++ file: .. literalinclude:: example.hpp :language: c++ + :lines: 4- The following code can be use to find the variable named "c" using different strategies, and to print information about it: .. literalinclude:: example.py :language: python + :lines: 4- From 86fa96f6cfcd9a6178682f3f3664d314e9bbfb1e Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 28 Nov 2015 11:25:49 +0100 Subject: [PATCH 044/268] Move first example to examples page, rename example --- docs/examples.rst | 1 + docs/{example => examples/print-example}/example.hpp | 0 docs/{example => examples/print-example}/example.hpp.rst | 0 docs/{example => examples/print-example}/example.hpp.xml | 0 .../{example => examples/print-example}/example.hpp.xml.rst | 0 docs/{example => examples/print-example}/example.py | 0 docs/{example => examples/print-example}/example.py.rst | 0 docs/{example => examples/print-example}/example.rst | 6 +++--- docs/{example => examples/print-example}/output.txt | 0 docs/{example => examples/print-example}/output.txt.rst | 0 docs/index.rst | 1 - 11 files changed, 4 insertions(+), 4 deletions(-) rename docs/{example => examples/print-example}/example.hpp (100%) rename docs/{example => examples/print-example}/example.hpp.rst (100%) rename docs/{example => examples/print-example}/example.hpp.xml (100%) rename docs/{example => examples/print-example}/example.hpp.xml.rst (100%) rename docs/{example => examples/print-example}/example.py (100%) rename docs/{example => examples/print-example}/example.py.rst (100%) rename docs/{example => examples/print-example}/example.rst (80%) rename docs/{example => examples/print-example}/output.txt (100%) rename docs/{example => examples/print-example}/output.txt.rst (100%) diff --git a/docs/examples.rst b/docs/examples.rst index 3e4ded34..38185d13 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -11,3 +11,4 @@ First examples examples/parsing/example.rst examples/variables/example.rst examples/caching/example.rst + examples/print-example/example.rst diff --git a/docs/example/example.hpp b/docs/examples/print-example/example.hpp similarity index 100% rename from docs/example/example.hpp rename to docs/examples/print-example/example.hpp diff --git a/docs/example/example.hpp.rst b/docs/examples/print-example/example.hpp.rst similarity index 100% rename from docs/example/example.hpp.rst rename to docs/examples/print-example/example.hpp.rst diff --git a/docs/example/example.hpp.xml b/docs/examples/print-example/example.hpp.xml similarity index 100% rename from docs/example/example.hpp.xml rename to docs/examples/print-example/example.hpp.xml diff --git a/docs/example/example.hpp.xml.rst b/docs/examples/print-example/example.hpp.xml.rst similarity index 100% rename from docs/example/example.hpp.xml.rst rename to docs/examples/print-example/example.hpp.xml.rst diff --git a/docs/example/example.py b/docs/examples/print-example/example.py similarity index 100% rename from docs/example/example.py rename to docs/examples/print-example/example.py diff --git a/docs/example/example.py.rst b/docs/examples/print-example/example.py.rst similarity index 100% rename from docs/example/example.py.rst rename to docs/examples/print-example/example.py.rst diff --git a/docs/example/example.rst b/docs/examples/print-example/example.rst similarity index 80% rename from docs/example/example.rst rename to docs/examples/print-example/example.rst index 71f3a89c..e4d7a918 100644 --- a/docs/example/example.rst +++ b/docs/examples/print-example/example.rst @@ -1,6 +1,6 @@ -======= -Example -======= +====================== +Print all declarations +====================== This example prints all declarations found in :doc:`example.hpp ` file. diff --git a/docs/example/output.txt b/docs/examples/print-example/output.txt similarity index 100% rename from docs/example/output.txt rename to docs/examples/print-example/output.txt diff --git a/docs/example/output.txt.rst b/docs/examples/print-example/output.txt.rst similarity index 100% rename from docs/example/output.txt.rst rename to docs/examples/print-example/output.txt.rst diff --git a/docs/index.rst b/docs/index.rst index 4011be14..72110bc6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -61,7 +61,6 @@ Documentation contents query_interface design upgrade_issues - example/example users links history From 02e6db31e15604e826e2eed586129c460bdc453a Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 1 Dec 2015 23:51:00 +0100 Subject: [PATCH 045/268] All the examples need to be tested for pep8 --- unittests/pep8_tester.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/unittests/pep8_tester.py b/unittests/pep8_tester.py index fd9a1de9..118fd46a 100644 --- a/unittests/pep8_tester.py +++ b/unittests/pep8_tester.py @@ -2,6 +2,7 @@ import os import pep8 import unittest +import fnmatch class tester_t(unittest.TestCase): @@ -46,9 +47,16 @@ def test_pep8_conformance_example(self): # Get the path to current directory path = os.path.dirname(os.path.realpath(__file__)) - path = path + "/../docs/example/" + path = path + "/../docs/examples/" - self.run_check(path) + # Find all the examples files + file_paths = [] + for root, dirnames, filenames in os.walk(path): + for file_path in fnmatch.filter(filenames, '*.py'): + file_paths.append(os.path.join(root, file_path)) + + for path in file_paths: + self.run_check(path) def test_pep8_conformance_setup(self): """Pep8 conformance test (setup) From 4cf76121460ff4d3850ee932f2b682749a186702 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 1 Dec 2015 23:51:26 +0100 Subject: [PATCH 046/268] All the examples need to be run --- unittests/example_tester.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/unittests/example_tester.py b/unittests/example_tester.py index 8f018fc1..9a1f11ad 100644 --- a/unittests/example_tester.py +++ b/unittests/example_tester.py @@ -1,5 +1,6 @@ import os +import fnmatch import unittest import subprocess @@ -20,11 +21,19 @@ def test_example(self): # Allows to cover files run in a subprocess # http://nedbatchelder.com/code/coverage/subprocess.html env["COVERAGE_PROCESS_START"] = path + "/../.coveragerc" - path += "/../docs/example/example.py" - return_code = subprocess.call(["python", path], env=env) - self.assertFalse( - return_code, - msg="The example did not run correctly") + path += "/../docs/examples" + + # Find all the examples files + file_paths = [] + for root, dirnames, filenames in os.walk(path): + for file_path in fnmatch.filter(filenames, '*.py'): + file_paths.append(os.path.join(root, file_path)) + + for file_path in file_paths: + return_code = subprocess.call(["python", file_path], env=env) + self.assertFalse( + return_code, + msg="The example %s did not run correctly" % file_path) def create_suite(): From 9e10fcd12e846782222b4aa9bdafed3e60b2efd3 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 1 Dec 2015 23:57:58 +0100 Subject: [PATCH 047/268] Correctly set the path for the examples, hide these lines in the documentation --- docs/examples/caching/example.py | 7 +++++++ docs/examples/caching/example.rst | 2 +- docs/examples/parsing/example.py | 7 +++++++ docs/examples/parsing/example.rst | 2 +- docs/examples/variables/example.py | 9 ++++++++- docs/examples/variables/example.rst | 2 +- 6 files changed, 25 insertions(+), 4 deletions(-) diff --git a/docs/examples/caching/example.py b/docs/examples/caching/example.py index 9522ded4..76a2fdd5 100644 --- a/docs/examples/caching/example.py +++ b/docs/examples/caching/example.py @@ -6,6 +6,12 @@ from pygccxml import declarations from pygccxml import parser +import os +import sys +# Find out the file location within the sources tree +this_module_dir_path = os.path.abspath( + os.path.dirname(sys.modules[__name__].__file__)) + # Find out the c++ parser generator_path, generator_name = utils.find_xml_generator() @@ -16,6 +22,7 @@ # The c++ file we want to parse filename = "example.hpp" +filename = this_module_dir_path + "/" + filename file_config = parser.file_configuration_t( data=filename, diff --git a/docs/examples/caching/example.rst b/docs/examples/caching/example.rst index 05a4e007..493b5d13 100644 --- a/docs/examples/caching/example.rst +++ b/docs/examples/caching/example.rst @@ -16,7 +16,7 @@ To enable caching, you can use the following code: .. literalinclude:: example.py :language: python - :lines: 4- + :lines: 5,6,7,14-24,26- The first time you run this example, the c++ file will be read and a xml file will be generated: diff --git a/docs/examples/parsing/example.py b/docs/examples/parsing/example.py index 2e718f7e..8493b902 100644 --- a/docs/examples/parsing/example.py +++ b/docs/examples/parsing/example.py @@ -6,6 +6,12 @@ from pygccxml import declarations from pygccxml import parser +import os +import sys +# Find out the file location within the sources tree +this_module_dir_path = os.path.abspath( + os.path.dirname(sys.modules[__name__].__file__)) + # Find the location of the xml generator (castxml or gccxml) generator_path, generator_name = utils.find_xml_generator() @@ -16,6 +22,7 @@ # The c++ file we want to parse filename = "example.hpp" +filename = this_module_dir_path + "/" + filename # Parse the c++ file decls = parser.parse([filename], xml_generator_config) diff --git a/docs/examples/parsing/example.rst b/docs/examples/parsing/example.rst index d9123a2f..01c7ca4a 100644 --- a/docs/examples/parsing/example.rst +++ b/docs/examples/parsing/example.rst @@ -17,4 +17,4 @@ and how to parse the c++ file: .. literalinclude:: example.py :language: python - :lines: 4- + :lines: 5,6,7,14-24,26- diff --git a/docs/examples/variables/example.py b/docs/examples/variables/example.py index ca6c1436..4585ab71 100644 --- a/docs/examples/variables/example.py +++ b/docs/examples/variables/example.py @@ -6,6 +6,12 @@ from pygccxml import declarations from pygccxml import parser +import os +import sys +# Find out the file location within the sources tree +this_module_dir_path = os.path.abspath( + os.path.dirname(sys.modules[__name__].__file__)) + # Find out the c++ parser generator_path, generator_name = utils.find_xml_generator() @@ -15,7 +21,8 @@ xml_generator=generator_name) # The c++ file we want to parse -filename = "variables.hpp" +filename = "example.hpp" +filename = this_module_dir_path + "/" + filename decls = parser.parse([filename], xml_generator_config) global_namespace = declarations.get_global_namespace(decls) diff --git a/docs/examples/variables/example.rst b/docs/examples/variables/example.rst index ef437cc4..574e0bb3 100644 --- a/docs/examples/variables/example.rst +++ b/docs/examples/variables/example.rst @@ -15,4 +15,4 @@ strategies, and to print information about it: .. literalinclude:: example.py :language: python - :lines: 4- + :lines: 5,6,7,14-24,26- From de420e124a6603f3536971baf70f3b0524fb23c1 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 3 Dec 2015 23:55:35 +0100 Subject: [PATCH 048/268] Use the sphinx readthedocs theme for the documentation --- docs/conf.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 9c5bb6b1..065b84ec 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,6 +14,7 @@ import sys import os +import sphinx_rtd_theme # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -100,7 +101,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'classic' +html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -108,7 +109,7 @@ #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". From 61129d449413c8e511bfd57f8ec7c545d4c5405c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 3 Dec 2015 23:57:02 +0100 Subject: [PATCH 049/268] Add example.hpp.xml file to .gitignore for caching example --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 438d00b2..bbcfb715 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ dist build pygccxml.egg-info *.prof -.coverage \ No newline at end of file +.coverage +docs/examples/caching/example.hpp.xml From a3369450c59811e5296db756a1dde45a33db938d Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 4 Dec 2015 19:06:17 +0100 Subject: [PATCH 050/268] Added example showing how to compare two declarations --- docs/examples.rst | 1 + docs/examples/equality/example.hpp | 13 ++++++++ docs/examples/equality/example.py | 49 ++++++++++++++++++++++++++++++ docs/examples/equality/example.rst | 18 +++++++++++ 4 files changed, 81 insertions(+) create mode 100644 docs/examples/equality/example.hpp create mode 100644 docs/examples/equality/example.py create mode 100644 docs/examples/equality/example.rst diff --git a/docs/examples.rst b/docs/examples.rst index 38185d13..037f0e71 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -10,5 +10,6 @@ First examples examples/parsing/example.rst examples/variables/example.rst + examples/equality/example.rst examples/caching/example.rst examples/print-example/example.rst diff --git a/docs/examples/equality/example.hpp b/docs/examples/equality/example.hpp new file mode 100644 index 00000000..5a097238 --- /dev/null +++ b/docs/examples/equality/example.hpp @@ -0,0 +1,13 @@ +// Copyright 2014-2015 Insight Software Consortium. +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +namespace ns{ + void func1(int a) { + int b = a; + } + + void func2(int a) { + int b = a; + } +} diff --git a/docs/examples/equality/example.py b/docs/examples/equality/example.py new file mode 100644 index 00000000..f0930867 --- /dev/null +++ b/docs/examples/equality/example.py @@ -0,0 +1,49 @@ +# Copyright 2014-2015 Insight Software Consortium. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +from pygccxml import utils +from pygccxml import declarations +from pygccxml import parser + +import os +import sys +# Find out the file location within the sources tree +this_module_dir_path = os.path.abspath( + os.path.dirname(sys.modules[__name__].__file__)) + +# Find the location of the xml generator (castxml or gccxml) +generator_path, generator_name = utils.find_xml_generator() + +# Configure the xml generator +xml_generator_config = parser.xml_generator_configuration_t( + xml_generator_path=generator_path, + xml_generator=generator_name) + +# The c++ file we want to parse +filename = "example.hpp" +filename = this_module_dir_path + "/" + filename + +# Parse the c++ file +decls = parser.parse([filename], xml_generator_config) + +global_namespace = declarations.get_global_namespace(decls) + +ns_namespace = global_namespace.namespace("ns") + +# Search for the function called func1 +criteria = declarations.calldef_matcher(name="func1") +func1a = declarations.matcher.get_single(criteria, ns_namespace) + +# Search for the function called func2 +criteria = declarations.calldef_matcher(name="func2") +func2a = declarations.matcher.get_single(criteria, ns_namespace) + +# You can also write a loop on the declaration tree +func1b = None +for decl in ns_namespace.declarations: + if decl.name == "func1": + func1b = decl + +# The declarations can be compared (prints (True, False)) +print(func1a == func1b, func1a == func2a) diff --git a/docs/examples/equality/example.rst b/docs/examples/equality/example.rst new file mode 100644 index 00000000..f7f150b2 --- /dev/null +++ b/docs/examples/equality/example.rst @@ -0,0 +1,18 @@ +========================== +Comparing two declarations +========================== + +This example shows how two declarations can be compared. + +Let's consider the following c++ file (example.hpp): + +.. literalinclude:: example.hpp + :language: c++ + :lines: 4- + +The following code will show you how to search for two functions, using +different ways. Both declarations are then compared. + +.. literalinclude:: example.py + :language: python + :lines: 5,6,7,14-24,26- \ No newline at end of file From 8867728dd8e8d2d00fe9247a169a9d6f97a6629a Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 4 Dec 2015 19:40:23 +0100 Subject: [PATCH 051/268] Add example showing how to search for declarations using matchers --- docs/examples.rst | 1 + docs/examples/searching/example.hpp | 24 ++++++++ docs/examples/searching/example.py | 85 +++++++++++++++++++++++++++++ docs/examples/searching/example.rst | 17 ++++++ 4 files changed, 127 insertions(+) create mode 100644 docs/examples/searching/example.hpp create mode 100644 docs/examples/searching/example.py create mode 100644 docs/examples/searching/example.rst diff --git a/docs/examples.rst b/docs/examples.rst index 037f0e71..625a6085 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -10,6 +10,7 @@ First examples examples/parsing/example.rst examples/variables/example.rst + examples/searching/example.rst examples/equality/example.rst examples/caching/example.rst examples/print-example/example.rst diff --git a/docs/examples/searching/example.hpp b/docs/examples/searching/example.hpp new file mode 100644 index 00000000..38802f5e --- /dev/null +++ b/docs/examples/searching/example.hpp @@ -0,0 +1,24 @@ +// Copyright 2014-2015 Insight Software Consortium. +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +namespace ns{ + int a = 1; + int b = 2; + double c = 3.0; + + int func1(int a) { + int b = a + 2; + return b; + } + + double func2(double a) { + double b = a + 2.0; + return b; + } + + double func3(double a) { + double b = a + 3.0; + return b; + } +} diff --git a/docs/examples/searching/example.py b/docs/examples/searching/example.py new file mode 100644 index 00000000..7a97e17c --- /dev/null +++ b/docs/examples/searching/example.py @@ -0,0 +1,85 @@ +# Copyright 2014-2015 Insight Software Consortium. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +from pygccxml import utils +from pygccxml import declarations +from pygccxml import parser + +import os +import sys +# Find out the file location within the sources tree +this_module_dir_path = os.path.abspath( + os.path.dirname(sys.modules[__name__].__file__)) + +# Find the location of the xml generator (castxml or gccxml) +generator_path, generator_name = utils.find_xml_generator() + +# Configure the xml generator +xml_generator_config = parser.xml_generator_configuration_t( + xml_generator_path=generator_path, + xml_generator=generator_name) + +# The c++ file we want to parse +filename = "example.hpp" +filename = this_module_dir_path + "/" + filename + +# Parse the c++ file +decls = parser.parse([filename], xml_generator_config) + +global_namespace = declarations.get_global_namespace(decls) + +ns_namespace = global_namespace.namespace("ns") + +int_type = declarations.cpptypes.int_t() +double_type = declarations.cpptypes.double_t() + +# Search for the function by name +criteria = declarations.calldef_matcher(name="func1") +funcA = declarations.matcher.get_single(criteria, ns_namespace) + +# Search for functions which return an int +criteria = declarations.calldef_matcher(return_type="int") +funcB = declarations.matcher.get_single(criteria, ns_namespace) + +# Search for functions which return an int, using the cpptypes class +criteria = declarations.calldef_matcher(return_type=int_type) +funcC = declarations.matcher.get_single(criteria, ns_namespace) + +print(funcA) +print(funcB) +print(funcC) + +# This prints: +# int ns::func1(int a) [free function] +# int ns::func1(int a) [free function] +# int ns::func1(int a) [free function] + +# Search for functions which return a double. Two functions will be found +criteria = declarations.calldef_matcher(return_type=double_type) +funcD = declarations.matcher.find(criteria, ns_namespace) + +print(len(funcD)) +print(funcD[0]) +print(funcD[1]) + +# This prints: +# 2 +# double ns::func2(double a) [free function] +# double ns::func3(double a) [free function] + +# Finally, look for variables by name and by type +criteria = declarations.variable_matcher(name="a") +var_a1 = declarations.matcher.find(criteria, ns_namespace) + +criteria = declarations.variable_matcher(type=int_type) +var_a2 = declarations.matcher.find(criteria, ns_namespace) + +print(var_a1[0]) +print(var_a2[0]) +print(var_a2[1]) + +# This prints: +# ns::a [variable] +# ns::a [variable] +# ns::b [variable] diff --git a/docs/examples/searching/example.rst b/docs/examples/searching/example.rst new file mode 100644 index 00000000..753c2695 --- /dev/null +++ b/docs/examples/searching/example.rst @@ -0,0 +1,17 @@ +============================================ +Searching for a declaration (using matchers) +============================================ + +This example shows how to search for a specific declaration using different criteria. + +Let's consider the following c++ file (example.hpp): + +.. literalinclude:: example.hpp + :language: c++ + :lines: 4- + +The following code will show you how to search for functions and variables + +.. literalinclude:: example.py + :language: python + :lines: 5,6,7,14-24,26- \ No newline at end of file From d5d3029e2c326d37465cf7e9240fdb82dc8e5943 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 6 Dec 2015 22:12:56 +0100 Subject: [PATCH 052/268] Add another example about searching declarations --- docs/examples.rst | 1 + docs/examples/searching1/example.hpp | 14 +++++++ docs/examples/searching1/example.py | 55 ++++++++++++++++++++++++++++ docs/examples/searching1/example.rst | 17 +++++++++ 4 files changed, 87 insertions(+) create mode 100644 docs/examples/searching1/example.hpp create mode 100644 docs/examples/searching1/example.py create mode 100644 docs/examples/searching1/example.rst diff --git a/docs/examples.rst b/docs/examples.rst index 625a6085..0563ec2a 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -10,6 +10,7 @@ First examples examples/parsing/example.rst examples/variables/example.rst + examples/searching1/example.rst examples/searching/example.rst examples/equality/example.rst examples/caching/example.rst diff --git a/docs/examples/searching1/example.hpp b/docs/examples/searching1/example.hpp new file mode 100644 index 00000000..f3088768 --- /dev/null +++ b/docs/examples/searching1/example.hpp @@ -0,0 +1,14 @@ +// Copyright 2014-2015 Insight Software Consortium. +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +namespace ns{ + int a = 1; + int b = 2; + double c = 3.0; + + double func2(double a) { + double b = a + 2.0; + return b; + } +} diff --git a/docs/examples/searching1/example.py b/docs/examples/searching1/example.py new file mode 100644 index 00000000..3ddf32d6 --- /dev/null +++ b/docs/examples/searching1/example.py @@ -0,0 +1,55 @@ +# Copyright 2014-2015 Insight Software Consortium. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +from pygccxml import utils +from pygccxml import declarations +from pygccxml import parser + +import os +import sys +# Find out the file location within the sources tree +this_module_dir_path = os.path.abspath( + os.path.dirname(sys.modules[__name__].__file__)) + +# Find the location of the xml generator (castxml or gccxml) +generator_path, generator_name = utils.find_xml_generator() + +# Configure the xml generator +xml_generator_config = parser.xml_generator_configuration_t( + xml_generator_path=generator_path, + xml_generator=generator_name) + +# The c++ file we want to parse +filename = "example.hpp" +filename = this_module_dir_path + "/" + filename + +# Parse the c++ file +decls = parser.parse([filename], xml_generator_config) + +global_namespace = declarations.get_global_namespace(decls) + +ns_namespace = global_namespace.namespace("ns") + +int_type = declarations.cpptypes.int_t() +double_type = declarations.cpptypes.double_t() + +for decl in ns_namespace.declarations: + print(decl) + +# This prints all the declarations in the namespace declaration tree: +# ns::a [variable] +# ns::b [variable] +# ns::c [variable] +# double ns::func2(double a) [free function] + +# Let's search for specific declarations +for decl in ns_namespace.declarations: + if decl.name == "b": + print(decl) + if isinstance(decl, declarations.calldef.free_function_t): + print(decl) + +# This prints: +# ns::b [variable] +# double ns::func2(double a) [free function] diff --git a/docs/examples/searching1/example.rst b/docs/examples/searching1/example.rst new file mode 100644 index 00000000..3104be59 --- /dev/null +++ b/docs/examples/searching1/example.rst @@ -0,0 +1,17 @@ +========================================== +Searching for a declaration (using a loop) +========================================== + +This example shows how to search for a specific declaration using a loop on the declarations tree. + +Let's consider the following c++ file (example.hpp): + +.. literalinclude:: example.hpp + :language: c++ + :lines: 4- + +The following code will show you how to loop on the tree and find a declaration + +.. literalinclude:: example.py + :language: python + :lines: 5,6,7,14-24,26- \ No newline at end of file From d7d1b1474a8cc75b9546f3da70d22dde71e32f0e Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 11 Dec 2015 19:08:08 +0100 Subject: [PATCH 053/268] Add comments in the is_copy_constructor method --- pygccxml/declarations/calldef.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index a029e876..3d19ff2a 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -736,22 +736,37 @@ def __str__(self): @property def is_copy_constructor(self): - """returns True if described declaration is copy constructor, - otherwise False""" + """ + Returns True if described declaration is copy constructor, + otherwise False + + """ + from . import type_traits + args = self.arguments - if 1 != len(args): + + # A copy constructor has only one argument + if len(args) != 1: return False + + # We have only one argument, get it arg = args[0] + + # The argument needs to be passed by reference in a copy constructor if not type_traits.is_reference(arg.type): return False + + # The argument needs to be const for a copy constructor if not type_traits.is_const(arg.type.base): return False - unaliased = type_traits.remove_alias(arg.type.base) - # unaliased now refers to const_t instance - if not isinstance(unaliased.base, cpptypes.declarated_t): + + un_aliased = type_traits.remove_alias(arg.type.base) + # un_aliased now refers to const_t instance + if not isinstance(un_aliased.base, cpptypes.declarated_t): return False - return id(unaliased.base.declaration) == id(self.parent) + + return id(un_aliased.base.declaration) == id(self.parent) @property def is_trivial_constructor(self): From 5dccece5fdbd4f2728da3e0e3e58cb3433970506 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 10 Jan 2016 21:19:33 +0100 Subject: [PATCH 054/268] Bump copyright year to 2016 --- docs/conf.py | 2 +- docs/examples/caching/example.hpp | 2 +- docs/examples/caching/example.py | 2 +- docs/examples/equality/example.hpp | 2 +- docs/examples/equality/example.py | 2 +- docs/examples/parsing/example.hpp | 2 +- docs/examples/parsing/example.py | 2 +- docs/examples/print-example/example.hpp | 2 +- docs/examples/print-example/example.py | 2 +- docs/examples/searching/example.hpp | 2 +- docs/examples/searching/example.py | 2 +- docs/examples/searching1/example.hpp | 2 +- docs/examples/searching1/example.py | 2 +- docs/examples/variables/example.hpp | 2 +- docs/examples/variables/example.py | 2 +- pygccxml/__init__.py | 2 +- pygccxml/binary_parsers/__init__.py | 2 +- pygccxml/binary_parsers/parsers.py | 2 +- pygccxml/binary_parsers/undname.py | 2 +- pygccxml/declarations/__init__.py | 2 +- pygccxml/declarations/algorithm.py | 2 +- pygccxml/declarations/algorithms_cache.py | 2 +- pygccxml/declarations/call_invocation.py | 2 +- pygccxml/declarations/calldef.py | 2 +- pygccxml/declarations/class_declaration.py | 2 +- pygccxml/declarations/container_traits.py | 2 +- pygccxml/declarations/cpptypes.py | 2 +- pygccxml/declarations/decl_factory.py | 2 +- pygccxml/declarations/decl_printer.py | 2 +- pygccxml/declarations/decl_visitor.py | 2 +- pygccxml/declarations/declaration.py | 2 +- pygccxml/declarations/dependencies.py | 2 +- pygccxml/declarations/enumeration.py | 2 +- pygccxml/declarations/function_traits.py | 2 +- pygccxml/declarations/location.py | 2 +- pygccxml/declarations/matcher.py | 2 +- pygccxml/declarations/matchers.py | 2 +- pygccxml/declarations/mdecl_wrapper.py | 2 +- pygccxml/declarations/namespace.py | 2 +- pygccxml/declarations/pattern_parser.py | 2 +- pygccxml/declarations/scopedef.py | 2 +- pygccxml/declarations/templates.py | 2 +- pygccxml/declarations/type_traits.py | 2 +- pygccxml/declarations/type_visitor.py | 2 +- pygccxml/declarations/typedef.py | 2 +- pygccxml/declarations/variable.py | 2 +- pygccxml/declarations/xml_generators.py | 2 +- pygccxml/parser/__init__.py | 2 +- pygccxml/parser/config.py | 2 +- pygccxml/parser/declarations_cache.py | 2 +- pygccxml/parser/directory_cache.py | 2 +- pygccxml/parser/etree_scanner.py | 2 +- pygccxml/parser/linker.py | 2 +- pygccxml/parser/patcher.py | 2 +- pygccxml/parser/project_reader.py | 2 +- pygccxml/parser/scanner.py | 2 +- pygccxml/parser/source_reader.py | 2 +- pygccxml/utils/__init__.py | 2 +- pygccxml/utils/utils.py | 2 +- setup.py | 2 +- unittests/algorithms_cache_tester.py | 2 +- unittests/array_bug_tester.py | 2 +- unittests/attributes_tester.py | 2 +- unittests/autoconfig.py | 2 +- unittests/better_templates_matcher_tester.py | 2 +- unittests/bit_fields_tester.py | 2 +- unittests/cache_enums_tester.py | 2 +- unittests/cached_source_file_tester.py | 2 +- unittests/call_invocation_tester.py | 2 +- unittests/calldef_matcher_tester.py | 2 +- unittests/calling_convention_tester.py | 2 +- unittests/complex_types_tester.py | 2 +- unittests/const_volatile_arg_tester.py | 2 +- unittests/copy_constructor_tester.py | 2 +- unittests/core_tester.py | 2 +- unittests/data/abstract_classes.hpp | 2 +- unittests/data/attributes_castxml.hpp | 2 +- unittests/data/attributes_gccxml.hpp | 2 +- unittests/data/basic.hpp | 2 +- unittests/data/better_templates_matcher_tester.hpp | 2 +- unittests/data/bit_fields.hpp | 2 +- unittests/data/classes.hpp | 2 +- unittests/data/complex_types.hpp | 2 +- unittests/data/const_volatile_arg.hpp | 2 +- unittests/data/core_cache.hpp | 2 +- unittests/data/core_class_hierarchy.hpp | 2 +- unittests/data/core_diamand_hierarchy_base.hpp | 2 +- unittests/data/core_diamand_hierarchy_derived1.hpp | 2 +- unittests/data/core_diamand_hierarchy_derived2.hpp | 2 +- unittests/data/core_diamand_hierarchy_final_derived.hpp | 2 +- unittests/data/core_membership.hpp | 2 +- unittests/data/core_ns_join_1.hpp | 2 +- unittests/data/core_ns_join_2.hpp | 2 +- unittests/data/core_ns_join_3.hpp | 2 +- unittests/data/core_overloads_1.hpp | 2 +- unittests/data/core_overloads_2.hpp | 2 +- unittests/data/core_types.hpp | 2 +- unittests/data/covariant_returns.hpp | 2 +- unittests/data/declaration_string.hpp | 2 +- unittests/data/declarations_calldef.hpp | 2 +- unittests/data/declarations_comparison.hpp | 2 +- unittests/data/declarations_enums.hpp | 2 +- unittests/data/declarations_for_filtering.hpp | 2 +- unittests/data/declarations_variables.hpp | 2 +- unittests/data/demangled.hpp | 2 +- unittests/data/free_operators.hpp | 2 +- unittests/data/has_public_binary_operator_traits.hpp | 2 +- unittests/data/include_all.hpp | 2 +- unittests/data/include_std.hpp | 2 +- unittests/data/indexing_suites2.hpp | 2 +- unittests/data/merge_free_functions.hpp | 2 +- unittests/data/non_copyable_classes.hpp | 2 +- unittests/data/patcher.hpp | 2 +- unittests/data/remove_template_defaults.hpp | 2 +- unittests/data/string_traits.hpp | 2 +- unittests/data/type_traits_castxml.hpp | 2 +- unittests/data/type_traits_gccxml.hpp | 2 +- unittests/data/typedefs1.hpp | 2 +- unittests/data/typedefs2.hpp | 2 +- unittests/data/typedefs_base.hpp | 2 +- unittests/data/unnamed_classes.hpp | 2 +- unittests/data/unnamed_enums_bug1.hpp | 2 +- unittests/data/unnamed_enums_bug2.hpp | 2 +- unittests/data/unnamed_ns_bug.hpp | 2 +- unittests/data/vector_traits.hpp | 2 +- unittests/decl_printer_tester.py | 2 +- unittests/decl_string_tester.py | 2 +- unittests/declaration_files_tester.py | 2 +- unittests/declaration_matcher_tester.py | 2 +- unittests/declarations_cache_tester.py | 2 +- unittests/declarations_comparison_tester.py | 2 +- unittests/declarations_tester.py | 2 +- unittests/demangled_tester.py | 2 +- unittests/dependencies_tester.py | 2 +- unittests/file_cache_tester.py | 2 +- unittests/filters_tester.py | 2 +- unittests/find_container_traits_tester.py | 2 +- unittests/free_operators_tester.py | 2 +- unittests/from_future_import_tester.py | 2 +- unittests/function_traits_tester.py | 2 +- unittests/gccxml10183_tester.py | 2 +- unittests/gccxml10184_tester.py | 2 +- unittests/gccxml10185_tester.py | 2 +- unittests/gccxml_runner_tester.py | 2 +- unittests/has_binary_operator_traits_tester.py | 2 +- unittests/hierarchy_traveling.py | 2 +- unittests/inline_specifier_tester.py | 2 +- unittests/misc/profile_parser.py | 2 +- unittests/misc/test_performance.py | 2 +- unittests/misc/timeit_test_parser.py | 2 +- unittests/namespace_matcher_tester.py | 2 +- unittests/non_copyable_classes_tester.py | 2 +- unittests/parser_test_case.py | 2 +- unittests/patcher_tester.py | 2 +- unittests/plain_c_tester.py | 2 +- unittests/project_reader_correctness_tester.py | 2 +- unittests/remove_template_defaults_tester.py | 2 +- unittests/source_reader_tester.py | 2 +- unittests/start_with_declarations_tester.py | 2 +- unittests/string_traits_tester.py | 2 +- unittests/templates_tester.py | 2 +- unittests/test_all.py | 2 +- unittests/test_create_decl_string.py | 2 +- unittests/test_utils.py | 2 +- unittests/test_va_list_tag_removal.py | 2 +- unittests/text_reader_tester.py | 2 +- unittests/type_as_exception_bug_tester.py | 2 +- unittests/type_traits_tester.py | 2 +- unittests/typedefs_tester.py | 2 +- unittests/undname_creator_tester.py | 2 +- unittests/unnamed_classes_tester.py | 2 +- unittests/unnamed_enums_bug_tester.py | 2 +- unittests/variable_matcher_tester.py | 2 +- unittests/vector_traits_tester.py | 2 +- unittests/xmlfile_reader_tester.py | 2 +- 175 files changed, 175 insertions(+), 175 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 065b84ec..abd7dc14 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -47,7 +47,7 @@ # General information about the project. project = u'pygccxml' -copyright = u'2014-2015, Insight Software Consortium' +copyright = u'2014-2016, Insight Software Consortium' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/docs/examples/caching/example.hpp b/docs/examples/caching/example.hpp index 4bbdcb61..9b97155b 100644 --- a/docs/examples/caching/example.hpp +++ b/docs/examples/caching/example.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/docs/examples/caching/example.py b/docs/examples/caching/example.py index 76a2fdd5..5af86abb 100644 --- a/docs/examples/caching/example.py +++ b/docs/examples/caching/example.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/docs/examples/equality/example.hpp b/docs/examples/equality/example.hpp index 5a097238..a89fe046 100644 --- a/docs/examples/equality/example.hpp +++ b/docs/examples/equality/example.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/docs/examples/equality/example.py b/docs/examples/equality/example.py index f0930867..b5be5795 100644 --- a/docs/examples/equality/example.py +++ b/docs/examples/equality/example.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/docs/examples/parsing/example.hpp b/docs/examples/parsing/example.hpp index 4bbdcb61..9b97155b 100644 --- a/docs/examples/parsing/example.hpp +++ b/docs/examples/parsing/example.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/docs/examples/parsing/example.py b/docs/examples/parsing/example.py index 8493b902..dce78ed9 100644 --- a/docs/examples/parsing/example.py +++ b/docs/examples/parsing/example.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/docs/examples/print-example/example.hpp b/docs/examples/print-example/example.hpp index 10d3b63f..05f1cd46 100644 --- a/docs/examples/print-example/example.hpp +++ b/docs/examples/print-example/example.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2009 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/docs/examples/print-example/example.py b/docs/examples/print-example/example.py index 84a2fc24..c5d4244a 100644 --- a/docs/examples/print-example/example.py +++ b/docs/examples/print-example/example.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/docs/examples/searching/example.hpp b/docs/examples/searching/example.hpp index 38802f5e..5466fa1a 100644 --- a/docs/examples/searching/example.hpp +++ b/docs/examples/searching/example.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/docs/examples/searching/example.py b/docs/examples/searching/example.py index 7a97e17c..bfcb20a3 100644 --- a/docs/examples/searching/example.py +++ b/docs/examples/searching/example.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/docs/examples/searching1/example.hpp b/docs/examples/searching1/example.hpp index f3088768..4f402248 100644 --- a/docs/examples/searching1/example.hpp +++ b/docs/examples/searching1/example.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/docs/examples/searching1/example.py b/docs/examples/searching1/example.py index 3ddf32d6..4d91a45c 100644 --- a/docs/examples/searching1/example.py +++ b/docs/examples/searching1/example.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/docs/examples/variables/example.hpp b/docs/examples/variables/example.hpp index 9fc88f69..13d6bca0 100644 --- a/docs/examples/variables/example.hpp +++ b/docs/examples/variables/example.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/docs/examples/variables/example.py b/docs/examples/variables/example.py index 4585ab71..b66ed40d 100644 --- a/docs/examples/variables/example.py +++ b/docs/examples/variables/example.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/__init__.py b/pygccxml/__init__.py index b4dcd451..d8fb828f 100644 --- a/pygccxml/__init__.py +++ b/pygccxml/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/binary_parsers/__init__.py b/pygccxml/binary_parsers/__init__.py index 334441d0..8ab29ba2 100644 --- a/pygccxml/binary_parsers/__init__.py +++ b/pygccxml/binary_parsers/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/binary_parsers/parsers.py b/pygccxml/binary_parsers/parsers.py index b29c8725..9d9ee149 100644 --- a/pygccxml/binary_parsers/parsers.py +++ b/pygccxml/binary_parsers/parsers.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/binary_parsers/undname.py b/pygccxml/binary_parsers/undname.py index 128f3178..09c0a212 100644 --- a/pygccxml/binary_parsers/undname.py +++ b/pygccxml/binary_parsers/undname.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index aaa73bf9..573b8442 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/algorithm.py b/pygccxml/declarations/algorithm.py index a42d7ce5..b089c8f0 100644 --- a/pygccxml/declarations/algorithm.py +++ b/pygccxml/declarations/algorithm.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/algorithms_cache.py b/pygccxml/declarations/algorithms_cache.py index a3247d13..6466f244 100644 --- a/pygccxml/declarations/algorithms_cache.py +++ b/pygccxml/declarations/algorithms_cache.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/call_invocation.py b/pygccxml/declarations/call_invocation.py index d01b4cc0..b0c37483 100644 --- a/pygccxml/declarations/call_invocation.py +++ b/pygccxml/declarations/call_invocation.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index 3d19ff2a..db0d5d7f 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 1d9f01c4..822d374f 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/container_traits.py b/pygccxml/declarations/container_traits.py index 5434f2cc..545c1469 100644 --- a/pygccxml/declarations/container_traits.py +++ b/pygccxml/declarations/container_traits.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/cpptypes.py b/pygccxml/declarations/cpptypes.py index 65066e76..e8d4a40d 100644 --- a/pygccxml/declarations/cpptypes.py +++ b/pygccxml/declarations/cpptypes.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/decl_factory.py b/pygccxml/declarations/decl_factory.py index e4296fd5..718a0a03 100644 --- a/pygccxml/declarations/decl_factory.py +++ b/pygccxml/declarations/decl_factory.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/decl_printer.py b/pygccxml/declarations/decl_printer.py index 40ca7fad..07dd18d9 100644 --- a/pygccxml/declarations/decl_printer.py +++ b/pygccxml/declarations/decl_printer.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko, 2006 Allen Bierbaum, Matthias Baas # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/decl_visitor.py b/pygccxml/declarations/decl_visitor.py index bdbf5ce1..1c15a1ae 100644 --- a/pygccxml/declarations/decl_visitor.py +++ b/pygccxml/declarations/decl_visitor.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/declaration.py b/pygccxml/declarations/declaration.py index 7a52beec..9b72566a 100644 --- a/pygccxml/declarations/declaration.py +++ b/pygccxml/declarations/declaration.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/dependencies.py b/pygccxml/declarations/dependencies.py index 2a8fe9ef..8350f180 100644 --- a/pygccxml/declarations/dependencies.py +++ b/pygccxml/declarations/dependencies.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/enumeration.py b/pygccxml/declarations/enumeration.py index 841ad890..6b1c4f64 100644 --- a/pygccxml/declarations/enumeration.py +++ b/pygccxml/declarations/enumeration.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/function_traits.py b/pygccxml/declarations/function_traits.py index 879950b5..07fb99b3 100644 --- a/pygccxml/declarations/function_traits.py +++ b/pygccxml/declarations/function_traits.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/location.py b/pygccxml/declarations/location.py index 39a336c7..3f93c5e5 100644 --- a/pygccxml/declarations/location.py +++ b/pygccxml/declarations/location.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/matcher.py b/pygccxml/declarations/matcher.py index 91b220d9..8779b710 100644 --- a/pygccxml/declarations/matcher.py +++ b/pygccxml/declarations/matcher.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/matchers.py b/pygccxml/declarations/matchers.py index c7b29654..b98c5cbf 100644 --- a/pygccxml/declarations/matchers.py +++ b/pygccxml/declarations/matchers.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/mdecl_wrapper.py b/pygccxml/declarations/mdecl_wrapper.py index abb09664..929fff38 100644 --- a/pygccxml/declarations/mdecl_wrapper.py +++ b/pygccxml/declarations/mdecl_wrapper.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/namespace.py b/pygccxml/declarations/namespace.py index 7364b493..b534985e 100644 --- a/pygccxml/declarations/namespace.py +++ b/pygccxml/declarations/namespace.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/pattern_parser.py b/pygccxml/declarations/pattern_parser.py index 2321d023..81acdd27 100644 --- a/pygccxml/declarations/pattern_parser.py +++ b/pygccxml/declarations/pattern_parser.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/scopedef.py b/pygccxml/declarations/scopedef.py index dfcf0538..da1e58f6 100644 --- a/pygccxml/declarations/scopedef.py +++ b/pygccxml/declarations/scopedef.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/templates.py b/pygccxml/declarations/templates.py index 2d3aa7f7..2fe34d17 100644 --- a/pygccxml/declarations/templates.py +++ b/pygccxml/declarations/templates.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 0d60f664..f29bf29e 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/type_visitor.py b/pygccxml/declarations/type_visitor.py index 451d1e7c..b5acd6c8 100644 --- a/pygccxml/declarations/type_visitor.py +++ b/pygccxml/declarations/type_visitor.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/typedef.py b/pygccxml/declarations/typedef.py index 0b927e9d..5ea7bf21 100644 --- a/pygccxml/declarations/typedef.py +++ b/pygccxml/declarations/typedef.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/variable.py b/pygccxml/declarations/variable.py index 73f05b3f..4f42e418 100644 --- a/pygccxml/declarations/variable.py +++ b/pygccxml/declarations/variable.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/declarations/xml_generators.py b/pygccxml/declarations/xml_generators.py index 9abecd79..831ebd08 100644 --- a/pygccxml/declarations/xml_generators.py +++ b/pygccxml/declarations/xml_generators.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/parser/__init__.py b/pygccxml/parser/__init__.py index b966be5d..fa6ac90f 100644 --- a/pygccxml/parser/__init__.py +++ b/pygccxml/parser/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index 4730d619..a256e24d 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/parser/declarations_cache.py b/pygccxml/parser/declarations_cache.py index 6421cede..18708994 100644 --- a/pygccxml/parser/declarations_cache.py +++ b/pygccxml/parser/declarations_cache.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/parser/directory_cache.py b/pygccxml/parser/directory_cache.py index 6bf2d04c..960805e9 100644 --- a/pygccxml/parser/directory_cache.py +++ b/pygccxml/parser/directory_cache.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/parser/etree_scanner.py b/pygccxml/parser/etree_scanner.py index 81f1ec93..fb3204b7 100644 --- a/pygccxml/parser/etree_scanner.py +++ b/pygccxml/parser/etree_scanner.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/parser/linker.py b/pygccxml/parser/linker.py index 29fdcdcf..baf9e4d8 100644 --- a/pygccxml/parser/linker.py +++ b/pygccxml/parser/linker.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/parser/patcher.py b/pygccxml/parser/patcher.py index 87ada735..2c7e250a 100644 --- a/pygccxml/parser/patcher.py +++ b/pygccxml/parser/patcher.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/parser/project_reader.py b/pygccxml/parser/project_reader.py index f75ffd55..dda73a77 100644 --- a/pygccxml/parser/project_reader.py +++ b/pygccxml/parser/project_reader.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index a7b94ccf..f41a1783 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 93713f58..43270419 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/utils/__init__.py b/pygccxml/utils/__init__.py index 6fc4c23a..cead420a 100644 --- a/pygccxml/utils/__init__.py +++ b/pygccxml/utils/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index 0d7c92be..5dd92d7e 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/setup.py b/setup.py index f84f62f0..ca202ea4 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/algorithms_cache_tester.py b/unittests/algorithms_cache_tester.py index d37af347..94dbef41 100644 --- a/unittests/algorithms_cache_tester.py +++ b/unittests/algorithms_cache_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/array_bug_tester.py b/unittests/array_bug_tester.py index 9ee183d1..e943c4b3 100644 --- a/unittests/array_bug_tester.py +++ b/unittests/array_bug_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/attributes_tester.py b/unittests/attributes_tester.py index 798aec2f..9b9c27cb 100644 --- a/unittests/attributes_tester.py +++ b/unittests/attributes_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/autoconfig.py b/unittests/autoconfig.py index ebee2175..e517f31b 100644 --- a/unittests/autoconfig.py +++ b/unittests/autoconfig.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/better_templates_matcher_tester.py b/unittests/better_templates_matcher_tester.py index a839820c..7eed0ab7 100644 --- a/unittests/better_templates_matcher_tester.py +++ b/unittests/better_templates_matcher_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/bit_fields_tester.py b/unittests/bit_fields_tester.py index f53d2921..b2c93a17 100644 --- a/unittests/bit_fields_tester.py +++ b/unittests/bit_fields_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/cache_enums_tester.py b/unittests/cache_enums_tester.py index 69f87cd6..6b6a3590 100644 --- a/unittests/cache_enums_tester.py +++ b/unittests/cache_enums_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/cached_source_file_tester.py b/unittests/cached_source_file_tester.py index a87f5009..3539c8a3 100644 --- a/unittests/cached_source_file_tester.py +++ b/unittests/cached_source_file_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/call_invocation_tester.py b/unittests/call_invocation_tester.py index be8f72e4..c52f204e 100644 --- a/unittests/call_invocation_tester.py +++ b/unittests/call_invocation_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/calldef_matcher_tester.py b/unittests/calldef_matcher_tester.py index 400389b2..85e17888 100644 --- a/unittests/calldef_matcher_tester.py +++ b/unittests/calldef_matcher_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/calling_convention_tester.py b/unittests/calling_convention_tester.py index b7759d6b..30716d85 100644 --- a/unittests/calling_convention_tester.py +++ b/unittests/calling_convention_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/complex_types_tester.py b/unittests/complex_types_tester.py index e07ace2c..5327d794 100644 --- a/unittests/complex_types_tester.py +++ b/unittests/complex_types_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/const_volatile_arg_tester.py b/unittests/const_volatile_arg_tester.py index 5264a831..623d5b79 100644 --- a/unittests/const_volatile_arg_tester.py +++ b/unittests/const_volatile_arg_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/copy_constructor_tester.py b/unittests/copy_constructor_tester.py index ebfb0f10..e22dd751 100644 --- a/unittests/copy_constructor_tester.py +++ b/unittests/copy_constructor_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/core_tester.py b/unittests/core_tester.py index 4fe30cee..394271b8 100644 --- a/unittests/core_tester.py +++ b/unittests/core_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/abstract_classes.hpp b/unittests/data/abstract_classes.hpp index 89f9e70a..9489a139 100644 --- a/unittests/data/abstract_classes.hpp +++ b/unittests/data/abstract_classes.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/attributes_castxml.hpp b/unittests/data/attributes_castxml.hpp index c37b697e..fb971e08 100644 --- a/unittests/data/attributes_castxml.hpp +++ b/unittests/data/attributes_castxml.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/attributes_gccxml.hpp b/unittests/data/attributes_gccxml.hpp index b8cd8953..d488ed75 100644 --- a/unittests/data/attributes_gccxml.hpp +++ b/unittests/data/attributes_gccxml.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/basic.hpp b/unittests/data/basic.hpp index e2204700..e2a90793 100644 --- a/unittests/data/basic.hpp +++ b/unittests/data/basic.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2009 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/better_templates_matcher_tester.hpp b/unittests/data/better_templates_matcher_tester.hpp index 2c29ff47..2080b6e1 100644 --- a/unittests/data/better_templates_matcher_tester.hpp +++ b/unittests/data/better_templates_matcher_tester.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/bit_fields.hpp b/unittests/data/bit_fields.hpp index 53fd1b89..0795719f 100644 --- a/unittests/data/bit_fields.hpp +++ b/unittests/data/bit_fields.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/classes.hpp b/unittests/data/classes.hpp index 72a290bc..e2017db9 100644 --- a/unittests/data/classes.hpp +++ b/unittests/data/classes.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/complex_types.hpp b/unittests/data/complex_types.hpp index e47da691..44968641 100644 --- a/unittests/data/complex_types.hpp +++ b/unittests/data/complex_types.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/const_volatile_arg.hpp b/unittests/data/const_volatile_arg.hpp index cd8e0afa..209c5a31 100644 --- a/unittests/data/const_volatile_arg.hpp +++ b/unittests/data/const_volatile_arg.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/core_cache.hpp b/unittests/data/core_cache.hpp index b4980d89..212b2111 100644 --- a/unittests/data/core_cache.hpp +++ b/unittests/data/core_cache.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/core_class_hierarchy.hpp b/unittests/data/core_class_hierarchy.hpp index 236c5358..1e1c31f2 100644 --- a/unittests/data/core_class_hierarchy.hpp +++ b/unittests/data/core_class_hierarchy.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/core_diamand_hierarchy_base.hpp b/unittests/data/core_diamand_hierarchy_base.hpp index 21c98336..90c19a8a 100644 --- a/unittests/data/core_diamand_hierarchy_base.hpp +++ b/unittests/data/core_diamand_hierarchy_base.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/core_diamand_hierarchy_derived1.hpp b/unittests/data/core_diamand_hierarchy_derived1.hpp index 10e4dd27..728d9e4c 100644 --- a/unittests/data/core_diamand_hierarchy_derived1.hpp +++ b/unittests/data/core_diamand_hierarchy_derived1.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/core_diamand_hierarchy_derived2.hpp b/unittests/data/core_diamand_hierarchy_derived2.hpp index 43dfd574..bc363c68 100644 --- a/unittests/data/core_diamand_hierarchy_derived2.hpp +++ b/unittests/data/core_diamand_hierarchy_derived2.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/core_diamand_hierarchy_final_derived.hpp b/unittests/data/core_diamand_hierarchy_final_derived.hpp index a1472f5c..0670b230 100644 --- a/unittests/data/core_diamand_hierarchy_final_derived.hpp +++ b/unittests/data/core_diamand_hierarchy_final_derived.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/core_membership.hpp b/unittests/data/core_membership.hpp index d6b71be1..e6e00c47 100644 --- a/unittests/data/core_membership.hpp +++ b/unittests/data/core_membership.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/core_ns_join_1.hpp b/unittests/data/core_ns_join_1.hpp index 5eb6b3c8..7dec6c38 100644 --- a/unittests/data/core_ns_join_1.hpp +++ b/unittests/data/core_ns_join_1.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/core_ns_join_2.hpp b/unittests/data/core_ns_join_2.hpp index 88259218..9da0a984 100644 --- a/unittests/data/core_ns_join_2.hpp +++ b/unittests/data/core_ns_join_2.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/core_ns_join_3.hpp b/unittests/data/core_ns_join_3.hpp index 81849414..9fd80181 100644 --- a/unittests/data/core_ns_join_3.hpp +++ b/unittests/data/core_ns_join_3.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/core_overloads_1.hpp b/unittests/data/core_overloads_1.hpp index 5ebdb5d9..7a5e991b 100644 --- a/unittests/data/core_overloads_1.hpp +++ b/unittests/data/core_overloads_1.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/core_overloads_2.hpp b/unittests/data/core_overloads_2.hpp index e4416d2b..e2a3f041 100644 --- a/unittests/data/core_overloads_2.hpp +++ b/unittests/data/core_overloads_2.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/core_types.hpp b/unittests/data/core_types.hpp index ceaf7303..9f4c0991 100644 --- a/unittests/data/core_types.hpp +++ b/unittests/data/core_types.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/covariant_returns.hpp b/unittests/data/covariant_returns.hpp index b822b00d..fcd3ec41 100644 --- a/unittests/data/covariant_returns.hpp +++ b/unittests/data/covariant_returns.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/declaration_string.hpp b/unittests/data/declaration_string.hpp index 5c76eb7b..4c17f64e 100644 --- a/unittests/data/declaration_string.hpp +++ b/unittests/data/declaration_string.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/declarations_calldef.hpp b/unittests/data/declarations_calldef.hpp index 47311cc5..5c877f99 100644 --- a/unittests/data/declarations_calldef.hpp +++ b/unittests/data/declarations_calldef.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/declarations_comparison.hpp b/unittests/data/declarations_comparison.hpp index 264be358..30256ddf 100644 --- a/unittests/data/declarations_comparison.hpp +++ b/unittests/data/declarations_comparison.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/declarations_enums.hpp b/unittests/data/declarations_enums.hpp index 5f8b744c..ec8f9e5e 100644 --- a/unittests/data/declarations_enums.hpp +++ b/unittests/data/declarations_enums.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/declarations_for_filtering.hpp b/unittests/data/declarations_for_filtering.hpp index 9aa9f44a..d8800ee4 100644 --- a/unittests/data/declarations_for_filtering.hpp +++ b/unittests/data/declarations_for_filtering.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/declarations_variables.hpp b/unittests/data/declarations_variables.hpp index 2ef9fea1..ec608f55 100644 --- a/unittests/data/declarations_variables.hpp +++ b/unittests/data/declarations_variables.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/demangled.hpp b/unittests/data/demangled.hpp index 78b4be60..561857d5 100644 --- a/unittests/data/demangled.hpp +++ b/unittests/data/demangled.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/free_operators.hpp b/unittests/data/free_operators.hpp index 045cec16..961a2e01 100644 --- a/unittests/data/free_operators.hpp +++ b/unittests/data/free_operators.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/has_public_binary_operator_traits.hpp b/unittests/data/has_public_binary_operator_traits.hpp index 00084542..6a7b9b47 100644 --- a/unittests/data/has_public_binary_operator_traits.hpp +++ b/unittests/data/has_public_binary_operator_traits.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/include_all.hpp b/unittests/data/include_all.hpp index e4a00c5b..4b78d19a 100644 --- a/unittests/data/include_all.hpp +++ b/unittests/data/include_all.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/include_std.hpp b/unittests/data/include_std.hpp index 03c998b3..c1a4ffd5 100644 --- a/unittests/data/include_std.hpp +++ b/unittests/data/include_std.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/indexing_suites2.hpp b/unittests/data/indexing_suites2.hpp index 77b356b7..1799ee68 100644 --- a/unittests/data/indexing_suites2.hpp +++ b/unittests/data/indexing_suites2.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/merge_free_functions.hpp b/unittests/data/merge_free_functions.hpp index c38955b8..3d185317 100644 --- a/unittests/data/merge_free_functions.hpp +++ b/unittests/data/merge_free_functions.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/non_copyable_classes.hpp b/unittests/data/non_copyable_classes.hpp index d4674e10..aaa0501c 100644 --- a/unittests/data/non_copyable_classes.hpp +++ b/unittests/data/non_copyable_classes.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/patcher.hpp b/unittests/data/patcher.hpp index 8a0082a8..03f4d5eb 100644 --- a/unittests/data/patcher.hpp +++ b/unittests/data/patcher.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/remove_template_defaults.hpp b/unittests/data/remove_template_defaults.hpp index 9a198e35..6db5cc55 100644 --- a/unittests/data/remove_template_defaults.hpp +++ b/unittests/data/remove_template_defaults.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/string_traits.hpp b/unittests/data/string_traits.hpp index c4485b81..25e8d6d3 100644 --- a/unittests/data/string_traits.hpp +++ b/unittests/data/string_traits.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/type_traits_castxml.hpp b/unittests/data/type_traits_castxml.hpp index ad2af6f9..29e84b19 100644 --- a/unittests/data/type_traits_castxml.hpp +++ b/unittests/data/type_traits_castxml.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/type_traits_gccxml.hpp b/unittests/data/type_traits_gccxml.hpp index 1e174344..58503dcf 100644 --- a/unittests/data/type_traits_gccxml.hpp +++ b/unittests/data/type_traits_gccxml.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/typedefs1.hpp b/unittests/data/typedefs1.hpp index 15395234..872477dd 100644 --- a/unittests/data/typedefs1.hpp +++ b/unittests/data/typedefs1.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/typedefs2.hpp b/unittests/data/typedefs2.hpp index 28a1c958..ab07abcc 100644 --- a/unittests/data/typedefs2.hpp +++ b/unittests/data/typedefs2.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/typedefs_base.hpp b/unittests/data/typedefs_base.hpp index a850ace5..faad436e 100644 --- a/unittests/data/typedefs_base.hpp +++ b/unittests/data/typedefs_base.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/unnamed_classes.hpp b/unittests/data/unnamed_classes.hpp index cade90a1..b5f29e49 100644 --- a/unittests/data/unnamed_classes.hpp +++ b/unittests/data/unnamed_classes.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/unnamed_enums_bug1.hpp b/unittests/data/unnamed_enums_bug1.hpp index 598b5660..aa2578ed 100644 --- a/unittests/data/unnamed_enums_bug1.hpp +++ b/unittests/data/unnamed_enums_bug1.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/unnamed_enums_bug2.hpp b/unittests/data/unnamed_enums_bug2.hpp index ac596b54..a0aa430b 100644 --- a/unittests/data/unnamed_enums_bug2.hpp +++ b/unittests/data/unnamed_enums_bug2.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/unnamed_ns_bug.hpp b/unittests/data/unnamed_ns_bug.hpp index cb83fea0..d38b4d02 100644 --- a/unittests/data/unnamed_ns_bug.hpp +++ b/unittests/data/unnamed_ns_bug.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/vector_traits.hpp b/unittests/data/vector_traits.hpp index c64c703c..71d02d53 100644 --- a/unittests/data/vector_traits.hpp +++ b/unittests/data/vector_traits.hpp @@ -1,4 +1,4 @@ -// Copyright 2014-2015 Insight Software Consortium. +// Copyright 2014-2016 Insight Software Consortium. // Copyright 2004-2008 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/decl_printer_tester.py b/unittests/decl_printer_tester.py index f209b483..2345b299 100644 --- a/unittests/decl_printer_tester.py +++ b/unittests/decl_printer_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/decl_string_tester.py b/unittests/decl_string_tester.py index 1c7540c1..41fad1f6 100644 --- a/unittests/decl_string_tester.py +++ b/unittests/decl_string_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/declaration_files_tester.py b/unittests/declaration_files_tester.py index 9ef23377..4a0b87c5 100644 --- a/unittests/declaration_files_tester.py +++ b/unittests/declaration_files_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/declaration_matcher_tester.py b/unittests/declaration_matcher_tester.py index 2f16e14a..bc523a99 100644 --- a/unittests/declaration_matcher_tester.py +++ b/unittests/declaration_matcher_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/declarations_cache_tester.py b/unittests/declarations_cache_tester.py index 1e1f8520..fc7c0aa9 100644 --- a/unittests/declarations_cache_tester.py +++ b/unittests/declarations_cache_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/declarations_comparison_tester.py b/unittests/declarations_comparison_tester.py index 16b3ef11..7843578f 100644 --- a/unittests/declarations_comparison_tester.py +++ b/unittests/declarations_comparison_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/declarations_tester.py b/unittests/declarations_tester.py index ac0e884b..410b038a 100644 --- a/unittests/declarations_tester.py +++ b/unittests/declarations_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/demangled_tester.py b/unittests/demangled_tester.py index 403c59b2..d0b73bd5 100644 --- a/unittests/demangled_tester.py +++ b/unittests/demangled_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/dependencies_tester.py b/unittests/dependencies_tester.py index db746bab..020ec9fc 100644 --- a/unittests/dependencies_tester.py +++ b/unittests/dependencies_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/file_cache_tester.py b/unittests/file_cache_tester.py index 8fd74d01..c5084f85 100644 --- a/unittests/file_cache_tester.py +++ b/unittests/file_cache_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/filters_tester.py b/unittests/filters_tester.py index 673f1363..ee53e50b 100644 --- a/unittests/filters_tester.py +++ b/unittests/filters_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/find_container_traits_tester.py b/unittests/find_container_traits_tester.py index 38220ef5..dc80edba 100644 --- a/unittests/find_container_traits_tester.py +++ b/unittests/find_container_traits_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/free_operators_tester.py b/unittests/free_operators_tester.py index 9f0bf02f..2531c753 100644 --- a/unittests/free_operators_tester.py +++ b/unittests/free_operators_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/from_future_import_tester.py b/unittests/from_future_import_tester.py index 3bb98d82..8db6ef3a 100644 --- a/unittests/from_future_import_tester.py +++ b/unittests/from_future_import_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/function_traits_tester.py b/unittests/function_traits_tester.py index 1a6eb9cf..ed0aaef7 100644 --- a/unittests/function_traits_tester.py +++ b/unittests/function_traits_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/gccxml10183_tester.py b/unittests/gccxml10183_tester.py index 1562042a..25a6c07f 100644 --- a/unittests/gccxml10183_tester.py +++ b/unittests/gccxml10183_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/gccxml10184_tester.py b/unittests/gccxml10184_tester.py index 5333abf5..75a657f9 100644 --- a/unittests/gccxml10184_tester.py +++ b/unittests/gccxml10184_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/gccxml10185_tester.py b/unittests/gccxml10185_tester.py index 276ea4c7..e7e32391 100644 --- a/unittests/gccxml10185_tester.py +++ b/unittests/gccxml10185_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/gccxml_runner_tester.py b/unittests/gccxml_runner_tester.py index 18bad4b3..4762414d 100644 --- a/unittests/gccxml_runner_tester.py +++ b/unittests/gccxml_runner_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/has_binary_operator_traits_tester.py b/unittests/has_binary_operator_traits_tester.py index 77abbaed..00178485 100644 --- a/unittests/has_binary_operator_traits_tester.py +++ b/unittests/has_binary_operator_traits_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/hierarchy_traveling.py b/unittests/hierarchy_traveling.py index 2c37c0e9..22510571 100644 --- a/unittests/hierarchy_traveling.py +++ b/unittests/hierarchy_traveling.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/inline_specifier_tester.py b/unittests/inline_specifier_tester.py index 7e85bbcc..408e2b26 100644 --- a/unittests/inline_specifier_tester.py +++ b/unittests/inline_specifier_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/misc/profile_parser.py b/unittests/misc/profile_parser.py index 7ca942ca..1445957d 100644 --- a/unittests/misc/profile_parser.py +++ b/unittests/misc/profile_parser.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/misc/test_performance.py b/unittests/misc/test_performance.py index e05a7fd3..b2fbb0a0 100644 --- a/unittests/misc/test_performance.py +++ b/unittests/misc/test_performance.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/misc/timeit_test_parser.py b/unittests/misc/timeit_test_parser.py index 97c252a0..cc31e7fb 100644 --- a/unittests/misc/timeit_test_parser.py +++ b/unittests/misc/timeit_test_parser.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/namespace_matcher_tester.py b/unittests/namespace_matcher_tester.py index f8100189..8872a602 100644 --- a/unittests/namespace_matcher_tester.py +++ b/unittests/namespace_matcher_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/non_copyable_classes_tester.py b/unittests/non_copyable_classes_tester.py index 359d9009..c8c52d91 100644 --- a/unittests/non_copyable_classes_tester.py +++ b/unittests/non_copyable_classes_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/parser_test_case.py b/unittests/parser_test_case.py index 8cfbd6f4..b65dac48 100644 --- a/unittests/parser_test_case.py +++ b/unittests/parser_test_case.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/patcher_tester.py b/unittests/patcher_tester.py index 8e7ac2da..5047d2ef 100644 --- a/unittests/patcher_tester.py +++ b/unittests/patcher_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/plain_c_tester.py b/unittests/plain_c_tester.py index b76d48b5..511aa62f 100644 --- a/unittests/plain_c_tester.py +++ b/unittests/plain_c_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/project_reader_correctness_tester.py b/unittests/project_reader_correctness_tester.py index fdd346ef..6b5fed4f 100644 --- a/unittests/project_reader_correctness_tester.py +++ b/unittests/project_reader_correctness_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/remove_template_defaults_tester.py b/unittests/remove_template_defaults_tester.py index 257577dc..35165f08 100644 --- a/unittests/remove_template_defaults_tester.py +++ b/unittests/remove_template_defaults_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/source_reader_tester.py b/unittests/source_reader_tester.py index 306a1b07..7f6247fa 100644 --- a/unittests/source_reader_tester.py +++ b/unittests/source_reader_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/start_with_declarations_tester.py b/unittests/start_with_declarations_tester.py index 13cc862f..26430315 100644 --- a/unittests/start_with_declarations_tester.py +++ b/unittests/start_with_declarations_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/string_traits_tester.py b/unittests/string_traits_tester.py index 1dd50d4b..2bc67083 100644 --- a/unittests/string_traits_tester.py +++ b/unittests/string_traits_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/templates_tester.py b/unittests/templates_tester.py index 4a8546b9..524258c9 100644 --- a/unittests/templates_tester.py +++ b/unittests/templates_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/test_all.py b/unittests/test_all.py index 29ba536f..196e1dff 100644 --- a/unittests/test_all.py +++ b/unittests/test_all.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/test_create_decl_string.py b/unittests/test_create_decl_string.py index 65272740..7ab1342d 100644 --- a/unittests/test_create_decl_string.py +++ b/unittests/test_create_decl_string.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/test_utils.py b/unittests/test_utils.py index 19f20f70..6117b79f 100644 --- a/unittests/test_utils.py +++ b/unittests/test_utils.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/test_va_list_tag_removal.py b/unittests/test_va_list_tag_removal.py index 0fdb7df5..c1d7228a 100644 --- a/unittests/test_va_list_tag_removal.py +++ b/unittests/test_va_list_tag_removal.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/text_reader_tester.py b/unittests/text_reader_tester.py index 6105dc3c..6175f97a 100644 --- a/unittests/text_reader_tester.py +++ b/unittests/text_reader_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/type_as_exception_bug_tester.py b/unittests/type_as_exception_bug_tester.py index 0784dddf..a0967f5b 100644 --- a/unittests/type_as_exception_bug_tester.py +++ b/unittests/type_as_exception_bug_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/type_traits_tester.py b/unittests/type_traits_tester.py index 1c085dec..37d1fa49 100644 --- a/unittests/type_traits_tester.py +++ b/unittests/type_traits_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/typedefs_tester.py b/unittests/typedefs_tester.py index 6904faee..2d751160 100644 --- a/unittests/typedefs_tester.py +++ b/unittests/typedefs_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/undname_creator_tester.py b/unittests/undname_creator_tester.py index 9e2c6c0e..43ac26f0 100644 --- a/unittests/undname_creator_tester.py +++ b/unittests/undname_creator_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/unnamed_classes_tester.py b/unittests/unnamed_classes_tester.py index cc2fd5f3..ee0da5a0 100644 --- a/unittests/unnamed_classes_tester.py +++ b/unittests/unnamed_classes_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/unnamed_enums_bug_tester.py b/unittests/unnamed_enums_bug_tester.py index 23f66c9d..5776c873 100644 --- a/unittests/unnamed_enums_bug_tester.py +++ b/unittests/unnamed_enums_bug_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/variable_matcher_tester.py b/unittests/variable_matcher_tester.py index 1f9cfb4b..84a5369b 100644 --- a/unittests/variable_matcher_tester.py +++ b/unittests/variable_matcher_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/vector_traits_tester.py b/unittests/vector_traits_tester.py index 28d3b8c3..429ba427 100644 --- a/unittests/vector_traits_tester.py +++ b/unittests/vector_traits_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/xmlfile_reader_tester.py b/unittests/xmlfile_reader_tester.py index fac7da7d..06076ecb 100644 --- a/unittests/xmlfile_reader_tester.py +++ b/unittests/xmlfile_reader_tester.py @@ -1,4 +1,4 @@ -# Copyright 2014-2015 Insight Software Consortium. +# Copyright 2014-2016 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt From ede6618c25a708e092887db84959b6a4e3bb5661 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 10 Jan 2016 21:39:20 +0100 Subject: [PATCH 055/268] Use new style python class --- pygccxml/declarations/dependencies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygccxml/declarations/dependencies.py b/pygccxml/declarations/dependencies.py index 8350f180..b152d36e 100644 --- a/pygccxml/declarations/dependencies.py +++ b/pygccxml/declarations/dependencies.py @@ -12,7 +12,7 @@ from . import cpptypes -class impl_details: +class impl_details(object): @staticmethod def dig_declarations(depend_on_it): From fb26fd5b3a1b186a4456a52715e3894e94cb4524 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 16 Jan 2016 11:04:05 +0100 Subject: [PATCH 056/268] Remove redundant None argument from dict.get() calls --- pygccxml/parser/scanner.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index f41a1783..661fd98d 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -161,7 +161,7 @@ def endDocument(self): # updating membership members_mapping = {} for gccxml_id, members in self.__members.items(): - decl = self.__declarations.get(gccxml_id, None) + decl = self.__declarations.get(gccxml_id) if not decl or not isinstance(decl, declarations.scopedef_t): continue members_mapping[id(decl)] = members @@ -200,7 +200,7 @@ def startElement(self, name, attrs): if name in self.deep_declarations: self.__inst = obj self.__read_access(attrs) - element_id = attrs.get(XML_AN_ID, None) + element_id = attrs.get(XML_AN_ID) # With CastXML and clang some __va_list_tag declarations are # present in the tree: we do not want to have these in the tree. @@ -273,7 +273,7 @@ def __read_location(self, decl, attrs): line=int(attrs[XML_AN_LINE])) def __update_membership(self, attrs): - parent = attrs.get(XML_AN_CONTEXT, None) + parent = attrs.get(XML_AN_CONTEXT) if not parent: return if parent not in self.__members: @@ -290,7 +290,7 @@ def __read_artificial(self, decl, attrs): decl.is_artificial = attrs.get(XML_AN_ARTIFICIAL, False) def __read_mangled(self, decl, attrs): - mangled = attrs.get(XML_AN_MANGLED, None) + mangled = attrs.get(XML_AN_MANGLED) # the following patch is defined here for performance reasons if isinstance(mangled, bytes) and \ mangled.endswith(self.__mangled_suffix): @@ -298,10 +298,10 @@ def __read_mangled(self, decl, attrs): decl.mangled = mangled def __read_demangled(self, decl, attrs): - decl.demangled = attrs.get(XML_AN_DEMANGLED, None) + decl.demangled = attrs.get(XML_AN_DEMANGLED) def __read_attributes(self, decl, attrs): - decl.attributes = attrs.get(XML_AN_ATTRIBUTES, None) + decl.attributes = attrs.get(XML_AN_ATTRIBUTES) def __read_access(self, attrs): self.__access[ @@ -438,7 +438,7 @@ def __read_argument(self, attrs): 'arg%d' % len( self.__inst.arguments)) argument.type = attrs[XML_AN_TYPE] - argument.default_value = attrs.get(XML_AN_DEFAULT, None) + argument.default_value = attrs.get(XML_AN_DEFAULT) self.__read_attributes(argument, attrs) if 'CastXML' not in utils.xml_generator: # GCCXML only @@ -455,13 +455,13 @@ def __read_ellipsis(self, attrs): def __read_calldef(self, calldef, attrs, is_declaration): # destructor for example doesn't have return type - calldef.return_type = attrs.get(XML_AN_RETURNS, None) + calldef.return_type = attrs.get(XML_AN_RETURNS) if is_declaration: self.__calldefs.append(calldef) calldef.name = attrs.get(XML_AN_NAME, '') calldef.has_extern = attrs.get(XML_AN_EXTERN, False) calldef.has_inline = bool(attrs.get(XML_AN_INLINE, "") == "1") - throw_stmt = attrs.get(XML_AN_THROW, None) + throw_stmt = attrs.get(XML_AN_THROW) if None is throw_stmt: calldef.does_throw = True calldef.exceptions = [] @@ -507,7 +507,7 @@ def __read_variable(self, attrs): type_qualifiers = declarations.type_qualifiers_t() type_qualifiers.has_mutable = attrs.get(XML_AN_MUTABLE, False) type_qualifiers.has_static = attrs.get(XML_AN_EXTERN, False) - bits = attrs.get(XML_AN_BITS, None) + bits = attrs.get(XML_AN_BITS) if bits: bits = int(bits) decl = self.__decl_factory.create_variable( @@ -517,8 +517,7 @@ def __read_variable(self, attrs): type=attrs[XML_AN_TYPE], type_qualifiers=type_qualifiers, value=attrs.get( - XML_AN_INIT, - None), + XML_AN_INIT), bits=bits) self.__read_byte_offset(decl, attrs) return decl From 74ffdde4cfb4731d27a7624b8dd6019330868812 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 17 Jan 2016 13:45:17 +0100 Subject: [PATCH 057/268] Add test to demonstrate error while using the is_copy_constructor method (issue #27) The code path used needs to be compared to gccxml in a next step and the error needs to be fixed. Then; the test can be further adapted. --- unittests/data/test_copy_constructor.hpp | 12 ++++++ unittests/test_copy_constructor.py | 47 ++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 unittests/data/test_copy_constructor.hpp create mode 100644 unittests/test_copy_constructor.py diff --git a/unittests/data/test_copy_constructor.hpp b/unittests/data/test_copy_constructor.hpp new file mode 100644 index 00000000..f05149da --- /dev/null +++ b/unittests/data/test_copy_constructor.hpp @@ -0,0 +1,12 @@ +// Copyright 2014-2016 Insight Software Consortium. +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +typedef const int & a; +class test +{ + public: + test(a t0) + { + } +}; diff --git a/unittests/test_copy_constructor.py b/unittests/test_copy_constructor.py new file mode 100644 index 00000000..8244df4a --- /dev/null +++ b/unittests/test_copy_constructor.py @@ -0,0 +1,47 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +import unittest +import parser_test_case + +from pygccxml import parser +from pygccxml import declarations + + +class tester_t(parser_test_case.parser_test_case_t): + + def __init__(self, *args): + parser_test_case.parser_test_case_t.__init__(self, *args) + self.header = "test_copy_constructor.hpp" + + def setUp(self): + decls = parser.parse([self.header], self.config) + self.global_ns = declarations.get_global_namespace(decls) + + def test(self): + """ + Check the is_copy_constructor method. + + This fails when using CastXML, see issue #27. + + """ + + tclass = self.global_ns.class_("test") + for decl in tclass.declarations: + if isinstance(decl, declarations.calldef.constructor_t): + #print(decl.arguments[0].name, decl.arguments[0].type) + print(decl.is_copy_constructor) + + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(tester_t)) + return suite + + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run(create_suite()) + +if __name__ == "__main__": + run_suite() From cb3895f81065aabc3775243394da65bc13b58c98 Mon Sep 17 00:00:00 2001 From: Mark Moll Date: Mon, 18 Jan 2016 20:50:03 -0600 Subject: [PATCH 058/268] SafeConfigParser is deprecated in python 3.2 and newer, so use ConfigParser instead. Add support for cflags property in config files --- pygccxml/parser/config.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index a256e24d..610b1f38 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -343,11 +343,11 @@ def load_xml_generator_configuration(configuration, **defaults): """ loads CastXML or GCC-XML configuration from an `.ini` file or any other file class - :class:`ConfigParser.SafeConfigParser` is able to parse. + :class:`configparser.ConfigParser` is able to parse. :param configuration: configuration could be string(configuration file path) or instance - of :class:`ConfigParser.SafeConfigParser` class + of :class:`configparser.ConfigParser` class :rtype: :class:`.xml_generator_configuration_t` @@ -381,10 +381,10 @@ def load_xml_generator_configuration(configuration, **defaults): parser = configuration if utils.is_str(configuration): try: - from configparser import SafeConfigParser + from configparser import ConfigParser except ImportError: - from ConfigParser import SafeConfigParser - parser = SafeConfigParser() + from ConfigParser import SafeConfigParser as ConfigParser + parser = ConfigParser() parser.read(configuration) # Create a new empty configuration @@ -419,6 +419,8 @@ def load_xml_generator_configuration(configuration, **defaults): cfg.xml_generator = value elif name == 'keep_xml': cfg.keep_xml = value + elif name == 'cflags': + cfg.cflags = value elif name == 'flags': cfg.flags = value elif name == 'compiler_path': From c110b93b6383f0f1d136b4e38869b991921b7a7c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 19 Jan 2016 20:31:47 +0100 Subject: [PATCH 059/268] Fix failing pep8 test --- unittests/test_copy_constructor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/test_copy_constructor.py b/unittests/test_copy_constructor.py index 8244df4a..264e7f92 100644 --- a/unittests/test_copy_constructor.py +++ b/unittests/test_copy_constructor.py @@ -30,7 +30,7 @@ def test(self): tclass = self.global_ns.class_("test") for decl in tclass.declarations: if isinstance(decl, declarations.calldef.constructor_t): - #print(decl.arguments[0].name, decl.arguments[0].type) + # print(decl.arguments[0].name, decl.arguments[0].type) print(decl.is_copy_constructor) From d0f863f42cd5406d881ea7669f7b80342dc000fe Mon Sep 17 00:00:00 2001 From: Mark Oates Date: Sun, 7 Feb 2016 02:21:30 -0500 Subject: [PATCH 060/268] Fix simple typo in example.py comment --- docs/examples/variables/example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/variables/example.py b/docs/examples/variables/example.py index b66ed40d..a42ab588 100644 --- a/docs/examples/variables/example.py +++ b/docs/examples/variables/example.py @@ -29,7 +29,7 @@ ns = global_namespace.namespace("ns") # The variables() method will return a list of variables. -# We know that he c variable is the third one in the list: +# We know that the c variable is the third one in the list: c = ns.variables()[2] print("My name is: " + c.name) print("My type is: " + str(c.type)) From 92ae9ec423252050fc15905405299bcb479b71f3 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 9 Feb 2016 23:23:08 +0100 Subject: [PATCH 061/268] Deprecate the ns() method No need to redeclare methods, and the longer names are preferred. The namespace() method can be used instead. --- pygccxml/declarations/namespace.py | 13 ++++++++++++- unittests/decl_string_tester.py | 2 +- unittests/declarations_tester.py | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/pygccxml/declarations/namespace.py b/pygccxml/declarations/namespace.py index b534985e..8b6772c9 100644 --- a/pygccxml/declarations/namespace.py +++ b/pygccxml/declarations/namespace.py @@ -105,7 +105,18 @@ def namespace(self, name=None, function=None, recursive=None): function=function, recursive=recursive) ) - ns = namespace + + def ns(self, name=None, function=None, recursive=None): + """ + Deprecated method. Use the namespace() method instead. + + """ + warnings.warn( + "The ns() method is deprecated. \n" + + "Please use the namespace() method instead.", + DeprecationWarning) + + return self.namespace(name, function, recursive) def namespaces( self, diff --git a/unittests/decl_string_tester.py b/unittests/decl_string_tester.py index 41fad1f6..f7509522 100644 --- a/unittests/decl_string_tester.py +++ b/unittests/decl_string_tester.py @@ -53,7 +53,7 @@ def test_free_function(self): "Created decl_string for global function contains mistake") def test_all_mem_and_free_funs(self): - ns = self.global_ns.ns('::declarations::calldef') + ns = self.global_ns.namespace('::declarations::calldef') for f in ns.mem_funs(): decls = parser.parse_string( self.template % f.decl_string, self.config) diff --git a/unittests/declarations_tester.py b/unittests/declarations_tester.py index 410b038a..2c4e71aa 100644 --- a/unittests/declarations_tester.py +++ b/unittests/declarations_tester.py @@ -245,7 +245,7 @@ def test_operator_symbol(self): decl.decl_string) def test_ellipsis(self): - ns = self.global_ns.ns('ellipsis_tester') + ns = self.global_ns.namespace('ellipsis_tester') do_smth = ns.mem_fun('do_smth') self.assertTrue(do_smth.has_ellipsis) do_smth_else = ns.free_fun('do_smth_else') From 40b8d1ac6657487179b2adf3e8806dd50e99392e Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 15 Feb 2016 23:38:34 +0100 Subject: [PATCH 062/268] Do not clutter tests with warnings when testing the deprecated compiler attribute This is known to throw a warning. The test will be removed once the compiler attribute is dropped. --- unittests/core_tester.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/unittests/core_tester.py b/unittests/core_tester.py index 394271b8..dd1776bf 100644 --- a/unittests/core_tester.py +++ b/unittests/core_tester.py @@ -4,6 +4,7 @@ # See http://www.boost.org/LICENSE_1_0.txt import pprint +import warnings try: import unittest2 as unittest except ImportError: @@ -161,9 +162,16 @@ def test_membership(self): declarations.ACCESS_TYPES.PRIVATE) def test_compiler_retrocompatibility(self): - # For retrocompatibility, test if the compiler - # attribute still works. This can be removed - # once compiler is dropped. + """ + For retro-compatibility, test if the compiler attribute still works. + + This can be removed once the compiler attribute is dropped. + + """ + + # Do not clutter the tests with warnings + warnings.simplefilter("ignore", DeprecationWarning) + std = self.global_ns.namespace("std") self.assertEqual(utils.xml_generator, std.compiler) if "GCC" in utils.xml_generator: @@ -171,6 +179,9 @@ def test_compiler_retrocompatibility(self): elif "CastXML" in utils.xml_generator: self.assertIn("CastXML", std.compiler) + # Reset this warning to always + warnings.simplefilter("always", DeprecationWarning) + def test_mangled_name_namespace(self): std = self.global_ns.namespace("std") self.assertTrue(std, "std namespace has not been found") From 13dd292c854fd0c48009f212b8c11ec01310de35 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 16 Feb 2016 00:01:20 +0100 Subject: [PATCH 063/268] Avoid empty exception handlers in patcher.py --- pygccxml/parser/patcher.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pygccxml/parser/patcher.py b/pygccxml/parser/patcher.py index 2c7e250a..a422042a 100644 --- a/pygccxml/parser/patcher.py +++ b/pygccxml/parser/patcher.py @@ -60,14 +60,16 @@ def __is_invalid_integral(self, func, arg): try: int(arg.default_value) return False - except: + except ValueError: + # The arg.default_value string could not be converted to int return True def __fix_invalid_integral(self, func, arg): try: int(arg.default_value) return arg.default_value - except: + except ValueError: + # The arg.default_value string could not be converted to int pass try: @@ -83,7 +85,8 @@ def __fix_invalid_integral(self, func, arg): if found_hex and not default_value.startswith('0x'): int('0x' + default_value, 16) return '0x' + default_value - except: + except ValueError: + # The arg.default_value string could not be converted to int pass # may be we deal with enum From 6bcd6e0526d7ac8566ea07ade1e6806610371896 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 16 Feb 2016 21:34:40 +0100 Subject: [PATCH 064/268] Replace failIf by assertFalse failIf is an alias for assertFalse, and is deprecated since python 2.7 --- unittests/core_tester.py | 2 +- unittests/type_traits_tester.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/unittests/core_tester.py b/unittests/core_tester.py index dd1776bf..b0b2bfbc 100644 --- a/unittests/core_tester.py +++ b/unittests/core_tester.py @@ -341,7 +341,7 @@ def test_fundamental_types(self): "there is a difference between typedef base type " + "name('%s') and expected one('%s')" % (typedef.type.decl_string, fundamental_type.decl_string)) - self.failIf(errors, pprint.pformat(errors)) + self.assertFalse(errors, pprint.pformat(errors)) def test_compound_types(self): typedef_inst = self.global_ns.decl( diff --git a/unittests/type_traits_tester.py b/unittests/type_traits_tester.py index 37d1fa49..5428be28 100644 --- a/unittests/type_traits_tester.py +++ b/unittests/type_traits_tester.py @@ -60,7 +60,9 @@ def __test_type_category(self, ns_name, controller): decl.name.startswith('test_'): continue - self.failIf(controller(decl), er % (decl.decl_string, ns_name)) + self.assertFalse( + controller(decl), + er % (decl.decl_string, ns_name)) def __test_type_transformation(self, ns_name, transformer): ns_control = declarations.find_declaration( @@ -215,7 +217,7 @@ def test_is_same(self): declarations.is_same( declarations.int_t, declarations.int_t)) - self.failIf( + self.assertFalse( declarations.is_same( declarations.int_t, declarations.float_t)) From 6261ef8abb5b65de15d59dffccadeca3d627be8f Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 16 Feb 2016 21:43:14 +0100 Subject: [PATCH 065/268] Replace assert_ by assertTrue assert_ was an alias for assertTrue, and is deprecated since python 2.7 --- unittests/declarations_cache_tester.py | 43 ++++++++++++----------- unittests/find_container_traits_tester.py | 4 +-- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/unittests/declarations_cache_tester.py b/unittests/declarations_cache_tester.py index fc7c0aa9..e3535814 100644 --- a/unittests/declarations_cache_tester.py +++ b/unittests/declarations_cache_tester.py @@ -27,8 +27,8 @@ def test_file_signature(self): sig1 = declarations_cache.file_signature(file1) sig1_dup = declarations_cache.file_signature(file1_dup) sig2 = declarations_cache.file_signature(file2) - self.assert_(sig1 == sig1_dup) - self.assert_(sig1 != sig2) + self.assertTrue(sig1 == sig1_dup) + self.assertTrue(sig1 != sig2) def test_config_signature(self): diff_cfg_list = self.build_differing_cfg_list() @@ -37,21 +37,22 @@ def test_config_signature(self): # Test changes that should cause sig changes for cfg in diff_cfg_list[1:]: - self.assert_( + self.assertTrue( declarations_cache.configuration_signature(cfg) != def_sig) # Test changes that should not cause sig changes no_changes = def_cfg.clone() - self.assert_( + self.assertTrue( declarations_cache.configuration_signature(no_changes) == def_sig) # start_decls_changed = def_cfg.clone() # start_decls_changed.start_with_declarations = "test object" - # self.assert_(configuration_signature(start_decls_changed) == def_sig) + # self.assertTrue( + # configuration_signature(start_decls_changed) == def_sig) ignore_changed = def_cfg.clone() ignore_changed.ignore_gccxml_output = True - self.assert_( + self.assertTrue( declarations_cache.configuration_signature( ignore_changed) == def_sig) @@ -71,41 +72,41 @@ def test_cache_interface(self): os.remove(cache_file) cache = declarations_cache.file_cache_t(cache_file) - self.assert_(len(cache._file_cache_t__cache) == 0) + self.assertTrue(len(cache._file_cache_t__cache) == 0) # test creating new entries for differing files cache.update(file1, def_cfg, 1, []) - self.assert_(len(cache._file_cache_t__cache) == 1) + self.assertTrue(len(cache._file_cache_t__cache) == 1) cache.update(file1_dup, def_cfg, 2, []) - self.assert_(len(cache._file_cache_t__cache) == 1) + self.assertTrue(len(cache._file_cache_t__cache) == 1) cache.update(file2, def_cfg, 3, []) - self.assert_(len(cache._file_cache_t__cache) == 2) + self.assertTrue(len(cache._file_cache_t__cache) == 2) - self.assert_(cache.cached_value(file1, def_cfg) == 2) - self.assert_(cache.cached_value(file2, def_cfg) == 3) + self.assertTrue(cache.cached_value(file1, def_cfg) == 2) + self.assertTrue(cache.cached_value(file2, def_cfg) == 3) # Test reading again cache.flush() cache = declarations_cache.file_cache_t(cache_file) - self.assert_(len(cache._file_cache_t__cache) == 2) - self.assert_(cache.cached_value(file1, def_cfg) == 2) - self.assert_(cache.cached_value(file2, def_cfg) == 3) + self.assertTrue(len(cache._file_cache_t__cache) == 2) + self.assertTrue(cache.cached_value(file1, def_cfg) == 2) + self.assertTrue(cache.cached_value(file2, def_cfg) == 3) # Test flushing doesn't happen if we don't touch the cache cache = declarations_cache.file_cache_t(cache_file) - self.assert_( + self.assertTrue( cache.cached_value( file1, def_cfg) == 2) # Read from cache cache.flush() # should not actually flush cache = declarations_cache.file_cache_t(cache_file) - self.assert_(len(cache._file_cache_t__cache) == 2) + self.assertTrue(len(cache._file_cache_t__cache) == 2) # Test flush culling cache = declarations_cache.file_cache_t(cache_file) cache.update(file1_dup, def_cfg, 4, []) # Modify cache cache.flush() # should cull off one entry cache = declarations_cache.file_cache_t(cache_file) - self.assert_(len(cache._file_cache_t__cache) == 1) + self.assertTrue(len(cache._file_cache_t__cache) == 1) def build_differing_cfg_list(self): """ Return a list of configurations that all differ. """ @@ -126,7 +127,7 @@ def build_differing_cfg_list(self): # inc_changed = def_cfg.clone() # inc_changed.include_paths = ["/var/tmp"] - # self.assert_(configuration_signature(inc_changed) != def_sig) + # self.assertTrue(configuration_signature(inc_changed) != def_sig) inc_changed = xml_generator_configuration_t( "xml_generator_path", '.', ['/var/tmp'], ['sym'], ['unsym'], None, False, "") @@ -134,7 +135,7 @@ def build_differing_cfg_list(self): # def_changed = def_cfg.clone() # def_changed.define_symbols = ["symbol"] - # self.assert_(configuration_signature(def_changed) != def_sig) + # self.assertTrue(configuration_signature(def_changed) != def_sig) def_changed = xml_generator_configuration_t( "xml_generator_path", '.', ['/var/tmp'], ['new-sym'], ['unsym'], None, False, "") @@ -142,7 +143,7 @@ def build_differing_cfg_list(self): # undef_changed = def_cfg.clone() # undef_changed.undefine_symbols = ["symbol"] - # self.assert_(configuration_signature(undef_changed) != def_sig) + # self.assertTrue(configuration_signature(undef_changed) != def_sig) undef_changed = xml_generator_configuration_t( "xml_generator_path", '.', ['/var/tmp'], ['sym'], ['new-unsym'], None, False, "") diff --git a/unittests/find_container_traits_tester.py b/unittests/find_container_traits_tester.py index dc80edba..bd7284a4 100644 --- a/unittests/find_container_traits_tester.py +++ b/unittests/find_container_traits_tester.py @@ -160,11 +160,11 @@ def test_remove_defaults_partial_name_namespace(self): # traits.remove_defaults(type_info) decl_string = cls.partial_decl_string key_type_string = traits.key_type(type_info).partial_decl_string - self.assert_( + self.assertTrue( decl_string.startswith('::std::'), "declaration string %r doesn't start with 'std::'" % decl_string) - self.assert_( + self.assertTrue( key_type_string.startswith('::std::'), "key type string %r doesn't start with 'std::'" % key_type_string) From 4e1e4979759ae19645331532775bd8bc40de325a Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 16 Feb 2016 22:22:16 +0100 Subject: [PATCH 066/268] Throw exceptions instead of warnings when running tests (see #29). This will allow us to be notified by the build bots, so that the warnings can be fixed. --- unittests/autoconfig.py | 6 ++++++ unittests/core_tester.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/unittests/autoconfig.py b/unittests/autoconfig.py index e517f31b..ee8c8d79 100644 --- a/unittests/autoconfig.py +++ b/unittests/autoconfig.py @@ -6,6 +6,7 @@ import os import sys import logging +import warnings this_module_dir_path = os.path.abspath( os.path.dirname(sys.modules[__name__].__file__)) @@ -23,6 +24,11 @@ import pygccxml.parser # nopep8 import pygccxml.utils # nopep8 +# We want to make sure we throw an error for ALL the warnings during the +# tests. This will allow us to be notified by the build bots, so that the +# warnings can be fixed. +warnings.simplefilter("error", Warning) + # Set logging level pygccxml.utils.loggers.set_level(logging.INFO) diff --git a/unittests/core_tester.py b/unittests/core_tester.py index b0b2bfbc..7f1b7973 100644 --- a/unittests/core_tester.py +++ b/unittests/core_tester.py @@ -180,7 +180,7 @@ def test_compiler_retrocompatibility(self): self.assertIn("CastXML", std.compiler) # Reset this warning to always - warnings.simplefilter("always", DeprecationWarning) + warnings.simplefilter("error", DeprecationWarning) def test_mangled_name_namespace(self): std = self.global_ns.namespace("std") From ff0b1f2fc909432620ede04f2a9238e92f9836ab Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 16 Feb 2016 22:34:56 +0100 Subject: [PATCH 067/268] Add error type to except, this is obviously an ImportError --- pygccxml/parser/source_reader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 43270419..e0d5d33d 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -13,7 +13,7 @@ try: # select the faster xml parser from .etree_scanner import etree_scanner_t as scanner_t -except: +except ImportError: from .scanner import scanner_t from . import declarations_cache From 98ed2ea06e6cce2e6889419844292c2128681c4d Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 17 Feb 2016 23:38:16 +0100 Subject: [PATCH 068/268] Document the release process a little bit --- docs/index.rst | 1 + docs/releasing.rst | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 docs/releasing.rst diff --git a/docs/index.rst b/docs/index.rst index 72110bc6..84d35a84 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -63,6 +63,7 @@ Documentation contents upgrade_issues users links + releasing history credits apidocs/api diff --git a/docs/releasing.rst b/docs/releasing.rst new file mode 100644 index 00000000..723de60f --- /dev/null +++ b/docs/releasing.rst @@ -0,0 +1,30 @@ +Releasing +========= + +To build a new release, the following files should be modified: + +Modify the version numbers in: + +``setup.py`` + +``pygccxml/__init__.py`` + +``docs/conf.py`` + +Do not forget to document the changes in the ``docs/history.rst`` file. + +Uploading to pypi +----------------- + +The documentation for the building and uploading can be found here: `pypi`_ + +The wheels are built with: + +``python setup.py bdist_wheel --universal`` + +They are uploaded with: + +``twine upload dist/*`` + + +.. _`pypi`: http://python-packaging-user-guide.readthedocs.org/en/latest/distributing/ From e0a100740c1040c7bc9f31d2d3fa7af3731dbbc0 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 18 Feb 2016 23:22:01 +0100 Subject: [PATCH 069/268] Do not declare variable twice --- pygccxml/binary_parsers/parsers.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pygccxml/binary_parsers/parsers.py b/pygccxml/binary_parsers/parsers.py index 9d9ee149..4ea79e1a 100644 --- a/pygccxml/binary_parsers/parsers.py +++ b/pygccxml/binary_parsers/parsers.py @@ -108,9 +108,6 @@ def parse(self): CCTS = declarations.CALLING_CONVENTION_TYPES -CCTS = declarations.CALLING_CONVENTION_TYPES - - class formated_mapping_parser_t(libparser_t): """convenience class, which formats existing declarations""" From 177b91d43a93b96d04e604f7d049e11d6bda84ab Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 19 Feb 2016 23:32:05 +0100 Subject: [PATCH 070/268] Remove unnecessary inits in tests. They were only passing *args through, without real usage. --- unittests/call_invocation_tester.py | 3 --- unittests/calling_convention_tester.py | 3 --- unittests/example_tester.py | 3 --- unittests/pep8_tester.py | 3 --- unittests/templates_tester.py | 3 --- unittests/type_traits_tester.py | 6 ------ 6 files changed, 21 deletions(-) diff --git a/unittests/call_invocation_tester.py b/unittests/call_invocation_tester.py index c52f204e..3177f998 100644 --- a/unittests/call_invocation_tester.py +++ b/unittests/call_invocation_tester.py @@ -9,9 +9,6 @@ class tester_t(unittest.TestCase): - def __init__(self, *args): - unittest.TestCase.__init__(self, *args) - def __test_split_impl(self, decl_string, name, args): self.assertTrue( (name, args) == declarations.call_invocation.split(decl_string)) diff --git a/unittests/calling_convention_tester.py b/unittests/calling_convention_tester.py index 30716d85..7c7a071f 100644 --- a/unittests/calling_convention_tester.py +++ b/unittests/calling_convention_tester.py @@ -9,9 +9,6 @@ class tester_t(unittest.TestCase): - def __init__(self, *args): - unittest.TestCase.__init__(self, *args) - def test_extract(self): data = [ ('thiscall', diff --git a/unittests/example_tester.py b/unittests/example_tester.py index 9a1f11ad..c494580f 100644 --- a/unittests/example_tester.py +++ b/unittests/example_tester.py @@ -7,9 +7,6 @@ class tester_t(unittest.TestCase): - def __init__(self, *args): - unittest.TestCase.__init__(self, *args) - def test_example(self): """Runs the example in the docs directory""" diff --git a/unittests/pep8_tester.py b/unittests/pep8_tester.py index 118fd46a..373ede57 100644 --- a/unittests/pep8_tester.py +++ b/unittests/pep8_tester.py @@ -7,9 +7,6 @@ class tester_t(unittest.TestCase): - def __init__(self, *args): - unittest.TestCase.__init__(self, *args) - def test_pep8_conformance_unitests(self): """Pep8 conformance test (unitests) diff --git a/unittests/templates_tester.py b/unittests/templates_tester.py index 524258c9..4fca1e63 100644 --- a/unittests/templates_tester.py +++ b/unittests/templates_tester.py @@ -10,9 +10,6 @@ class tester_t(unittest.TestCase): - def __init__(self, *args): - unittest.TestCase.__init__(self, *args) - def __test_split_impl(self, decl_string, name, args): self.assertTrue( (name, args) == declarations.templates.split(decl_string)) diff --git a/unittests/type_traits_tester.py b/unittests/type_traits_tester.py index 5428be28..9f5cb35f 100644 --- a/unittests/type_traits_tester.py +++ b/unittests/type_traits_tester.py @@ -352,9 +352,6 @@ def test_is_convertible(self): class missing_decls_tester_t(unittest.TestCase): - def __init__(self, *args): - unittest.TestCase.__init__(self, *args) - def test(self): config = autoconfig.cxx_parsers_cfg.gccxml code = "struct const_item{ const int values[10]; };" @@ -391,9 +388,6 @@ def test(self): class class_traits_tester_t(unittest.TestCase): - def __init__(self, *args): - unittest.TestCase.__init__(self, *args) - def test_get_declaration(self): code = """ namespace A{ From 7c6053b9ed304acb96b804963f6e654558d75c7c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 19 Feb 2016 23:33:12 +0100 Subject: [PATCH 071/268] Remove forgotten pass This pass does nothing, it's probably an old code artifact. --- unittests/hierarchy_traveling.py | 1 - 1 file changed, 1 deletion(-) diff --git a/unittests/hierarchy_traveling.py b/unittests/hierarchy_traveling.py index 22510571..7cdbb3c9 100644 --- a/unittests/hierarchy_traveling.py +++ b/unittests/hierarchy_traveling.py @@ -73,7 +73,6 @@ def test_recursive_derived(self): self.assertTrue(len(control_derived) == len(all_derived)) all_derived_names = [hi.related_class.name for hi in all_derived] self.assertTrue(set(all_derived_names) == control_derived) - pass def create_suite(): From 7f5b6e2db2b9ee927af668f86db4aca44878ac6c Mon Sep 17 00:00:00 2001 From: Mark Moll Date: Fri, 19 Feb 2016 23:48:45 -0600 Subject: [PATCH 072/268] pass C++11 flag to castxml --- pygccxml/parser/source_reader.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index e0d5d33d..0285cd11 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -161,7 +161,10 @@ def __create_command_line_castxml(self, source_file, xmlfile): else: # On mac or linux, use gcc or clang (the flag is the same) - cmd.append('--castxml-cc-gnu ' + self.__config.compiler_path) + if '-std=c++11' in self.__config.cflags: + cmd.append('--castxml-cc-gnu ' + '"(" ' + self.__config.compiler_path + ' -std=c++11 ")"') + else: + cmd.append('--castxml-cc-gnu ' + self.__config.compiler_path) # Tell castxml to output xml compatible files with gccxml # so that we can parse them with pygccxml From 9c133b5b9e1070d1721d57f6405d9cf1991d54b9 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 20 Feb 2016 23:59:32 +0100 Subject: [PATCH 073/268] Allow different c++ standards with castxml This extends the previous commit, and adds a test. See #33. --- pygccxml/parser/source_reader.py | 32 ++++++++++++++-- unittests/data/cpp_standards.hpp | 8 ++++ unittests/test_all.py | 4 +- unittests/test_cpp_standards.py | 63 ++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 unittests/data/cpp_standards.hpp create mode 100644 unittests/test_cpp_standards.py diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 0285cd11..65924bca 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -161,10 +161,36 @@ def __create_command_line_castxml(self, source_file, xmlfile): else: # On mac or linux, use gcc or clang (the flag is the same) - if '-std=c++11' in self.__config.cflags: - cmd.append('--castxml-cc-gnu ' + '"(" ' + self.__config.compiler_path + ' -std=c++11 ")"') + cmd.append('--castxml-cc-gnu ') + + # Check for -std=xx flags passed to the compiler. + # A regex could be used but this is a moving target. + # See c++1z for example. It is preferable to have a defined + # list of what is allowed. http://clang.llvm.org/cxx_status.html + # + # Version 98 and 03 are only there in the case somebody is using + # these flags; this is the equivalent to not passing these flags. + standards = [ + "-std=c++98", + "-std=c++03", + "-std=c++11", + "-std=c++14", + "-std=c++1z"] + + std_flag = "" + for standard in standards: + if standard in self.__config.cflags: + std_flag = " " + standard + " " + + # A -std= flag was passed, but is not in the list + if "-std=" in self.__config.cflags and std_flag == "": + raise(RuntimeError("Unknown -std=c++xx flag used !")) + + if std_flag != "": + cmd.append( + '"(" ' + self.__config.compiler_path + std_flag + '")"') else: - cmd.append('--castxml-cc-gnu ' + self.__config.compiler_path) + cmd.append(self.__config.compiler_path) # Tell castxml to output xml compatible files with gccxml # so that we can parse them with pygccxml diff --git a/unittests/data/cpp_standards.hpp b/unittests/data/cpp_standards.hpp new file mode 100644 index 00000000..3d500f07 --- /dev/null +++ b/unittests/data/cpp_standards.hpp @@ -0,0 +1,8 @@ +// Copyright 2014-2016 Insight Software Consortium. +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// A good test for different cpp standards. iostream is one of the first +// things to fail when the wrong flags are used. + +#include diff --git a/unittests/test_all.py b/unittests/test_all.py index 364bb9ce..fa49444e 100644 --- a/unittests/test_all.py +++ b/unittests/test_all.py @@ -68,6 +68,7 @@ import test_utils import test_va_list_tag_removal import test_copy_constructor +import test_cpp_standards testers = [ # , demangled_tester # failing right now @@ -128,7 +129,8 @@ example_tester, test_utils, test_va_list_tag_removal, - test_copy_constructor + test_copy_constructor, + test_cpp_standards ] if 'posix' in os.name: diff --git a/unittests/test_cpp_standards.py b/unittests/test_cpp_standards.py new file mode 100644 index 00000000..f5ccb413 --- /dev/null +++ b/unittests/test_cpp_standards.py @@ -0,0 +1,63 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +import unittest +import parser_test_case + +from pygccxml import parser +from pygccxml import utils + + +class Test(parser_test_case.parser_test_case_t): + + def test(self): + """ + Test different compilation standards by setting cflags. + + """ + + # Skip this test for gccxml, this is a CastXML feature. + if "gccxml" in self.config.xml_generator: + return True + + parser.parse(["cpp_standards.hpp"], self.config) + + self.config.cflags = "-std=c++98" + parser.parse(["cpp_standards.hpp"], self.config) + + self.config.cflags = "-std=c++03" + parser.parse(["cpp_standards.hpp"], self.config) + + self.config.cflags = "-std=c++11" + parser.parse(["cpp_standards.hpp"], self.config) + + # This is broken with llvm 3.6.2 (the one from homebrew) + # It should work with never llvms but I keep the test disabled + # See https://llvm.org/bugs/show_bug.cgi?id=24872 + # self.config.cflags = "-std=c++14" + # parser.parse(["cpp_standards.hpp"], self.config) + + # Same as above + # self.config.cflags = "-std=c++1z" + # parser.parse(["cpp_standards.hpp"], self.config) + + # Pass down a flag that does not exist. + # This should raise an exception. + self.config.cflags = "-std=c++00" + self.assertRaises( + RuntimeError, + lambda: parser.parse(["cpp_standards.hpp"], self.config)) + + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(Test)) + return suite + + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run(create_suite()) + +if __name__ == "__main__": + run_suite() From f4b071f191e6c4d2a60607bdf8d6a0ded084b07d Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 27 Feb 2016 16:50:09 +0100 Subject: [PATCH 074/268] Add support for clang 3.9 (trunk) (see bug #32) The fields without file defintion have been added to the list of tags which need to be skipped. --- pygccxml/parser/scanner.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index 661fd98d..c45070b2 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -261,9 +261,19 @@ def __read_location(self, decl, attrs): if "CastXML" in utils.xml_generator: # These fields are generated by clang, and have no location. # Just set an empty location for them. Gccxml does not have - # this problem. See also bug #19. + # this problem. + # bug #19: gp_offset, fp_offset, overflow_arg_area, reg_save_area + # bug #32: isa, flags, str and length were added in llvm 3.9 to_skip = [ - "gp_offset", "fp_offset", "overflow_arg_area", "reg_save_area"] + "gp_offset", + "fp_offset", + "overflow_arg_area", + "reg_save_area", + "isa", + "flags", + "str", + "length" + ] if "name" in attrs and attrs["name"] in to_skip: decl.location = declarations.location_t('', -1) From 3a2ece3265170207e1cbbbb0cb3c97629bdd1ea7 Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Wed, 2 Mar 2016 12:21:19 -0700 Subject: [PATCH 075/268] Fixes for Python2.6 and gcc + castxml unittest module in Python2.6 doesn't contain the methods 'assertIn' and 'assertNotIn', monkey patch these methods for versions < 2.7 gcc 4.4.7 and above, when using castxml, should use std::tr1 unordered containers instead of extensions provided under the __gnu_cxx namespace Cosmetic fix for xml generator name printed to stdout at the beginning of unit test execution --- unittests/autoconfig.py | 5 +++ unittests/data/remove_template_defaults.hpp | 40 ++++++++++++++++----- unittests/parser_test_case.py | 13 ++++--- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/unittests/autoconfig.py b/unittests/autoconfig.py index ee8c8d79..315d0504 100644 --- a/unittests/autoconfig.py +++ b/unittests/autoconfig.py @@ -56,6 +56,11 @@ class cxx_parsers_cfg(object): if 'msvc9' == gccxml.compiler: gccxml.define_symbols.append('_HAS_TR1=0') +if cxx_parsers_cfg.gccxml.xml_generator: + generator_name = cxx_parsers_cfg.gccxml.xml_generator +if cxx_parsers_cfg.gccxml.xml_generator_path: + generator_path = cxx_parsers_cfg.gccxml.xml_generator_path + print( '%s configured to simulate compiler %s' % (generator_name.title(), cxx_parsers_cfg.gccxml.compiler)) diff --git a/unittests/data/remove_template_defaults.hpp b/unittests/data/remove_template_defaults.hpp index 6db5cc55..ba51113e 100644 --- a/unittests/data/remove_template_defaults.hpp +++ b/unittests/data/remove_template_defaults.hpp @@ -8,7 +8,7 @@ #if defined( __llvm__ ) - // This is mostly for CastXML with never compilers + // This is mostly for CastXML with newer compilers // When parsing with clang//llvm use the new c++11 (c++0x even ?) // unordered_maps and unordered_sets @@ -38,9 +38,31 @@ // This is mostly for GCCXML (when using old compilers) #if defined( __GNUC__ ) - #include - #include - #define HASH_XXX_NS __gnu_cxx + #if ((__GNUC__ > 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ > 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ == 7)) && \ + defined(__castxml__) + + // Use TR1 containers for gcc >= 4.4.7 + castxml + // (this might work on older versions of gcc too, needs testing) + #include + #include + #define HASH_XXX_NS std::tr1 + + #define HASH_XXX_UMAP unordered_map + #define HASH_XXX_USET unordered_set + #define HASH_XXX_UMMAP unordered_multimap + #define HASH_XXX_UMMSET unordered_multiset + #else + #include + #include + #define HASH_XXX_NS __gnu_cxx + + #define HASH_XXX_UMAP hash_map + #define HASH_XXX_USET hash_set + #define HASH_XXX_UMMAP hash_multimap + #define HASH_XXX_UMMSET hash_multiset + #endif #else #include #include @@ -49,12 +71,12 @@ #else #define HASH_XXX_NS stdext #endif - #endif - #define HASH_XXX_UMAP hash_map - #define HASH_XXX_USET hash_set - #define HASH_XXX_UMMAP hash_multimap - #define HASH_XXX_UMMSET hash_multiset + #define HASH_XXX_UMAP hash_map + #define HASH_XXX_USET hash_set + #define HASH_XXX_UMMAP hash_multimap + #define HASH_XXX_UMMSET hash_multiset + #endif #endif diff --git a/unittests/parser_test_case.py b/unittests/parser_test_case.py index b65dac48..0b71affd 100644 --- a/unittests/parser_test_case.py +++ b/unittests/parser_test_case.py @@ -4,10 +4,8 @@ # See http://www.boost.org/LICENSE_1_0.txt import pprint -try: - import unittest2 as unittest -except ImportError: - import unittest +import sys +import unittest import autoconfig @@ -84,3 +82,10 @@ def _test_calldef_exceptions(self, calldef, exceptions): (calldef.name, pprint.pformat([delc.name for delc in exception_decls]), pprint.pformat([delc.name for delc in exceptions_indeed]))) + +if sys.version_info < (2, 7, 0): + # Python2.6 does not have the following methods in the unittest module + parser_test_case_t.assertIn = \ + lambda parser, a1, a2, *args: parser.assertTrue(a1 in a2, args) + parser_test_case_t.assertNotIn = \ + lambda parser, a1, a2, *args: parser.assertFalse(a1 in a2, args) From 7427bd493832520be528f9c6ae26485d1ba8df3f Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Tue, 8 Mar 2016 18:36:09 -0700 Subject: [PATCH 076/268] Typo fixes undname_creator_t.format_argtypes contained an undefined variable 'type_'. Comment spelling fix in scanner.py Change-Id: Ic6c030ba588f7f7de352254f3d3d671f8747f0f6 --- pygccxml/binary_parsers/undname.py | 5 +++-- pygccxml/parser/scanner.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pygccxml/binary_parsers/undname.py b/pygccxml/binary_parsers/undname.py index 09c0a212..b0af0ea4 100644 --- a/pygccxml/binary_parsers/undname.py +++ b/pygccxml/binary_parsers/undname.py @@ -187,8 +187,9 @@ def format_argtypes(self, argtypes, hint): # ugly hack, later, I will replace ', ' with ',', so single # space will still exist argsep = ', ' - return argsep.join(map(self.__format_type_as_undecorated( - type_, True, hint), argtypes)) + return argsep.join( + map(lambda type_: \ + self.__format_type_as_undecorated(type_, True, hint), argtypes)) def format_calldef(self, calldef, hint): calldef_type = calldef.function_type() diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index c45070b2..84684082 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -532,7 +532,7 @@ def __read_variable(self, attrs): self.__read_byte_offset(decl, attrs) return decl - __read_field = __read_variable # just a synonim + __read_field = __read_variable # just a synonym def __read_class_impl(self, class_type, attrs): name = attrs.get(XML_AN_NAME, '') From 91348c3e56ec891496c00bc7771e647791114c7d Mon Sep 17 00:00:00 2001 From: Mark Moll Date: Tue, 8 Mar 2016 21:04:26 -0600 Subject: [PATCH 077/268] classify std::shared_ptr as a smart pointer --- pygccxml/declarations/type_traits.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index f29bf29e..a897b47a 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -1166,7 +1166,7 @@ class smart_pointer_traits(object): @staticmethod def is_smart_pointer(type_): """returns True, if type represents instantiation of - `boost::shared_ptr`, False otherwise""" + `boost::shared_ptr` or `std::shared_ptr`, False otherwise""" type_ = remove_alias(type_) type_ = remove_cv(type_) type_ = remove_declarated(type_) @@ -1174,16 +1174,20 @@ def is_smart_pointer(type_): (class_declaration.class_declaration_t, class_declaration.class_t)): return False - if not impl_details.is_defined_in_xxx('boost', type_): + if not (impl_details.is_defined_in_xxx('boost', type_) or \ + impl_details.is_defined_in_xxx('std', type_)): return False - return type_.decl_string.startswith('::boost::shared_ptr<') + return type_.decl_string.startswith('::boost::shared_ptr<') or \ + type_.decl_string.startswith('::std::shared_ptr<') @staticmethod def value_type(type_): - """returns reference to `boost::shared_ptr` value type""" + """returns reference to `boost::shared_ptr` \ + or `std::shared_ptr` value type""" if not smart_pointer_traits.is_smart_pointer(type_): raise TypeError( - 'Type "%s" is not instantiation of boost::shared_ptr' % + 'Type "%s" is not an instantiation of \ + boost::shared_ptr or std::shared_ptr' % type_.decl_string) return internal_type_traits.get_by_name(type_, "value_type") From a25410d10c16e26c07d962fe05a454d2755a6e3b Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Tue, 8 Mar 2016 23:16:33 -0700 Subject: [PATCH 078/268] "is_union" type trait and unit tests Change-Id: I9f92881bce2afbe2db7160a3acefb21a0fbdd925 --- pygccxml/declarations/type_traits.py | 9 +++- unittests/data/unnamed_classes.hpp | 12 +++++- unittests/parser_test_case.py | 8 ++++ unittests/test_all.py | 4 +- unittests/unnamed_classes_tester.py | 63 ++++++++++++++++++++++++++-- 5 files changed, 89 insertions(+), 7 deletions(-) diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index f29bf29e..2960b0bf 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -365,8 +365,15 @@ def is_fundamental(type): (cpptypes.volatile_t, cpptypes.const_t)) -class declaration_xxx_traits(object): +def is_union(type_): + """returns True if type represents a C++ union""" + if not is_class(type_): + return False + decl = class_traits.get_declaration(type_) + return decl.class_type == class_declaration.CLASS_TYPES.UNION + +class declaration_xxx_traits(object): """this class implements the functionality needed for convenient work with declaration classes diff --git a/unittests/data/unnamed_classes.hpp b/unittests/data/unnamed_classes.hpp index b5f29e49..1e737558 100644 --- a/unittests/data/unnamed_classes.hpp +++ b/unittests/data/unnamed_classes.hpp @@ -25,7 +25,7 @@ struct S1{ unsigned int raw; } flags; - union FileAttribs{ + union /*FileAttribs*/{ struct{ unsigned int isReadOnly : 1; unsigned int isHidden : 1; @@ -45,6 +45,16 @@ struct S1{ unsigned int raw; } fileattribs; // in GetFileAttributes() format } header; + + struct S3{ + union + { + char anon_mem_c; + int anon_mem_i; + }; + long s3_mem; + S2 s2; + }; }; } // namespace diff --git a/unittests/parser_test_case.py b/unittests/parser_test_case.py index 0b71affd..8b1b6d63 100644 --- a/unittests/parser_test_case.py +++ b/unittests/parser_test_case.py @@ -89,3 +89,11 @@ def _test_calldef_exceptions(self, calldef, exceptions): lambda parser, a1, a2, *args: parser.assertTrue(a1 in a2, args) parser_test_case_t.assertNotIn = \ lambda parser, a1, a2, *args: parser.assertFalse(a1 in a2, args) + parser_test_case_t.assertIs = \ + lambda parser, a1, a2, *args: parser.assertTrue(a1 is a2, args) + parser_test_case_t.assertIsNot = \ + lambda parser, a1, a2, *args: parser.assertFalse(a1 is a2, args) + parser_test_case_t.assertIsNone = \ + lambda parser, a1, *args: parser.assertTrue(a1 is None, args) + parser_test_case_t.assertIsNotNone = \ + lambda parser, a1, *args: parser.assertFalse(a1 is None, args) diff --git a/unittests/test_all.py b/unittests/test_all.py index fa49444e..4cbed817 100644 --- a/unittests/test_all.py +++ b/unittests/test_all.py @@ -69,6 +69,7 @@ import test_va_list_tag_removal import test_copy_constructor import test_cpp_standards +import unnamed_classes_tester testers = [ # , demangled_tester # failing right now @@ -130,7 +131,8 @@ test_utils, test_va_list_tag_removal, test_copy_constructor, - test_cpp_standards + test_cpp_standards, + unnamed_classes_tester ] if 'posix' in os.name: diff --git a/unittests/unnamed_classes_tester.py b/unittests/unnamed_classes_tester.py index ee0da5a0..38c5b006 100644 --- a/unittests/unnamed_classes_tester.py +++ b/unittests/unnamed_classes_tester.py @@ -8,6 +8,7 @@ from pygccxml import parser from pygccxml import declarations +from pygccxml.declarations import type_traits class tester_t(parser_test_case.parser_test_case_t): @@ -23,10 +24,64 @@ def setUp(self): self.global_ns = declarations.get_global_namespace(decls) self.global_ns.init_optimizer() - def test(self): - # bf_x = self.global_ns.variable( 'x' ) - # self.assertTrue( bf_x.bits == 1 ) - pass + def validate_bitfields(self, parent, bitfields): + for key in bitfields: + var = parent.variable(key) + self.assertEqual(var.bits, bitfields[key]) + + def do_union_test(self, union_name, bitfields): + s2 = self.global_ns.class_('S2') + self.assertFalse(type_traits.is_union(s2)) + self.assertEqual(s2.parent.name, 'S1') + self.assertFalse(type_traits.is_union(s2.parent)) + + union = s2.variable(union_name) + self.assertTrue(type_traits.is_union(union.type)) + + union_type = type_traits.remove_declarated(union.type) + self.validate_bitfields(union_type, bitfields) + self.assertIsNotNone(union_type.variable('raw')) + + def test_union_Flags(self): + flags_bitfields = { + 'hasItemIdList': 1, + 'pointsToFileOrDir': 1, + 'hasDescription': 1, + 'hasRelativePath': 1, + 'hasWorkingDir': 1, + 'hasCmdLineArgs': 1, + 'hasCustomIcon': 1, + 'useWorkingDir': 1, + 'unused': 24, + } + self.do_union_test('flags', flags_bitfields) + + def test_unnamed_unions(self): + fileattribs_bitfields = { + 'isReadOnly': 1, + 'isHidden': 1, + 'isSystem': 1, + 'isVolumeLabel': 1, + 'isDir': 1, + 'isModified': 1, + 'isEncrypted': 1, + 'isNormal': 1, + 'isTemporary': 1, + 'isSparse': 1, + 'hasReparsePoint': 1, + 'isCompressed': 1, + 'isOffline': 1, + 'unused': 19, + } + self.do_union_test('fileattribs', fileattribs_bitfields) + + def test_anonymous_unions(self): + s3 = self.global_ns.class_('S3') + self.assertEqual(s3.parent.name, 'S1') + + s3_vars = ['anon_mem_c', 'anon_mem_i', 's3_mem', 's2'] + for var in s3_vars: + self.assertFalse(type_traits.is_union(s3.variable(var).type)) def create_suite(): From b8d977c201729aeb7d940567d8b8993e8e525657 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 10 Mar 2016 23:12:58 +0100 Subject: [PATCH 079/268] Pep8 cleanup --- pygccxml/declarations/type_traits.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index a897b47a..437c15c0 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -1174,8 +1174,8 @@ def is_smart_pointer(type_): (class_declaration.class_declaration_t, class_declaration.class_t)): return False - if not (impl_details.is_defined_in_xxx('boost', type_) or \ - impl_details.is_defined_in_xxx('std', type_)): + if not (impl_details.is_defined_in_xxx('boost', type_) or + impl_details.is_defined_in_xxx('std', type_)): return False return type_.decl_string.startswith('::boost::shared_ptr<') or \ type_.decl_string.startswith('::std::shared_ptr<') From ec4c7b7cfcbc71e0de3aea6e8b7a74ac68ce825e Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 10 Mar 2016 23:27:40 +0100 Subject: [PATCH 080/268] Pep8 cleanup --- pygccxml/binary_parsers/undname.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pygccxml/binary_parsers/undname.py b/pygccxml/binary_parsers/undname.py index b0af0ea4..b3c764c5 100644 --- a/pygccxml/binary_parsers/undname.py +++ b/pygccxml/binary_parsers/undname.py @@ -188,8 +188,8 @@ def format_argtypes(self, argtypes, hint): # space will still exist argsep = ', ' return argsep.join( - map(lambda type_: \ - self.__format_type_as_undecorated(type_, True, hint), argtypes)) + map(lambda type_: self.__format_type_as_undecorated( + type_, True, hint), argtypes)) def format_calldef(self, calldef, hint): calldef_type = calldef.function_type() From f1a925d987bd852329f84213be5af91de63423a5 Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Fri, 11 Mar 2016 02:01:19 -0700 Subject: [PATCH 081/268] Fix for typedef'd unnamed class/struct Unlike GCCXML, CastXML creates two distinct XML nodes for a typedef of the form typedef (class|struct) {} foo; The first XML node is an unnamed class/struct and the second is a typedef that refers to the first node. This requires special handling during parsing so that the name of the typedef is propagated to the class/struct. Change-Id: I91cc3753d50d41ff92c945a7b9801a0108163e6a --- pygccxml/declarations/__init__.py | 1 + pygccxml/parser/scanner.py | 35 +++++++++++++++++++++++++ unittests/data/classes.hpp | 6 +++++ unittests/declaration_matcher_tester.py | 22 ++++++++++++++++ 4 files changed, 64 insertions(+) diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 573b8442..9016e547 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -18,6 +18,7 @@ from .scopedef import scopedef_t from .enumeration import enumeration_t from .namespace import namespace_t +from .typedef import typedef_t from .class_declaration import class_t from .class_declaration import CLASS_TYPES diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index 84684082..5406f80b 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -221,6 +221,8 @@ def startElement(self, name, attrs): self.__read_location(obj, attrs) if isinstance(obj, declarations.class_t): self.__read_bases(obj, attrs) + if isinstance(obj, declarations.typedef_t): + self.__update_unnamed_class(obj, attrs) self.__read_artificial(obj, attrs) self.__read_mangled(obj, attrs) self.__read_demangled(obj, attrs) @@ -628,3 +630,36 @@ def __read_version(self, attrs): # compatibility. logger.debug('CASTXML version - None ( %s )', version_str) utils.xml_generator = declarations.xml_generators.CASTXML_None + + def __update_unnamed_class(self, decl, attrs): + """ + Called for typedef declarations. If CastXML is being used, then type + definitions with an unnamed class/struct are split across two nodes in + the XML tree. For example, + + typedef struct {} cls; + + produces + + + + + So we'll walk the list of read declarations and try to update an + unnamed class/struct with matching attributes + """ + if 'CastXML' not in utils.xml_generator: + return + + parent = attrs.get(XML_AN_CONTEXT) + if not parent: + return + if parent not in self.__members: + return + type_ = attrs.get(XML_AN_TYPE) + if not type_ or type_ not in self.__declarations: + return + + referent = self.__declarations[type_] + if referent.name or not isinstance(referent, declarations.class_t): + return + referent.name = decl.name diff --git a/unittests/data/classes.hpp b/unittests/data/classes.hpp index e2017db9..18567b30 100644 --- a/unittests/data/classes.hpp +++ b/unittests/data/classes.hpp @@ -7,10 +7,16 @@ #define __classes_hpp__ struct cls{}; +typedef struct {} cls2; +typedef class { + int i; +} cls3; namespace ns{ struct nested_cls{}; + typedef class {} nested_cls2; + typedef struct nested_cls3 {} nested_cls3; } diff --git a/unittests/declaration_matcher_tester.py b/unittests/declaration_matcher_tester.py index bc523a99..ab991111 100644 --- a/unittests/declaration_matcher_tester.py +++ b/unittests/declaration_matcher_tester.py @@ -8,6 +8,7 @@ from pygccxml import parser from pygccxml import declarations +from pygccxml import utils class tester_t(parser_test_case.parser_test_case_t): @@ -31,6 +32,19 @@ def test_global(self): gns.class_('cls') gns.class_('::cls') + def test_typedefs(self): + gns = self.global_ns + gns.class_('cls2') + if self.config.xml_generator == "castxml": + gns.typedef('cls2') + gns.class_('::cls2') + + gns.class_('cls3') + if self.config.xml_generator == "castxml": + gns.typedef('cls3') + cls3 = gns.class_('::cls3') + cls3.variable('i') + def test_ns1(self): gns = self.global_ns ns1 = gns.namespace('ns') @@ -43,6 +57,14 @@ def test_ns1(self): ns1.class_('nested_cls') ns1.class_('::ns::nested_cls') + gns.class_('nested_cls2') + self.assertRaises(Exception, lambda: gns.class_('ns::nested_cls2')) + gns.class_('::ns::nested_cls2') + + gns.class_('nested_cls3') + self.assertRaises(Exception, lambda: gns.class_('ns::nested_cls3')) + gns.class_('::ns::nested_cls3') + def create_suite(): suite = unittest.TestSuite() From 5783436c900d70ed540d7bd5456cfae6f25b4876 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 12 Mar 2016 11:46:37 +0100 Subject: [PATCH 082/268] Add castxml builds on Travis (closes #37) There are 4 new builds: - ubuntu 12.04 + castxml + py2/3 - os x (xcode 7.2) + castxml + py2/3 The castxml binaries are the same as the ones used to build ITK. --- .travis.yml | 102 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 87 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index b214b8af..2e63a846 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,25 +1,85 @@ language: - python -python: - - "2.6" - - "2.7" - - "3.2" - - "3.3" - - "3.4" - - "3.5" +matrix: + include: + - os: linux + python: 2.6 + env: XML_GENERATOR="gccxml" + - os: linux + python: 2.7 + env: XML_GENERATOR="gccxml" + - os: linux + python: 3.2 + env: XML_GENERATOR="gccxml" + - os: linux + python: 3.3 + env: XML_GENERATOR="gccxml" + - os: linux + python: 3.4 + env: XML_GENERATOR="gccxml" + - os: linux + python: 3.5 + env: XML_GENERATOR="gccxml" + - os: linux + python: 2.7 + env: XML_GENERATOR="castxml" + - os: linux + python: 3.5 + env: XML_GENERATOR="castxml" + - os: osx + osx_image: xcode7.2 + language: generic + env: + - XML_GENERATOR="castxml" + - TRAVIS_PYTHON_VERSION="2" + - os: osx + osx_image: xcode7.2 + language: generic + env: + - XML_GENERATOR="castxml" + - TRAVIS_PYTHON_VERSION="3" + before_install: - # Install gccxml - - sudo apt-get update -qq - - sudo apt-get install -qq gccxml + # OS X + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then travis_retry brew update; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ $TRAVIS_PYTHON_VERSION == 2 ]]; then brew install python; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ $TRAVIS_PYTHON_VERSION == 3 ]]; then brew install python3; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ $TRAVIS_PYTHON_VERSION == 3 ]]; then sudo ln -sf /usr/local/bin/pip3 /usr/local/bin/pip; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ $TRAVIS_PYTHON_VERSION == 3 ]]; then sudo ln -sf /usr/local/bin/python3 /usr/local/bin/python; fi + + # Download castxml binaries + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then + if [ ! -e ${HOME}/castxml ]; then + curl https://midas3.kitware.com/midas/download/item/318762/castxml-macosx.tar.gz | tar zxf - -C ${HOME}; + fi; + fi + + - if [[ "$TRAVIS_OS_NAME" == "linux" ]] && [[ $XML_GENERATOR == "castxml" ]]; then + if [ ! -e ${HOME}/castxml ]; then + wget -O - https://midas3.kitware.com/midas/download/item/318227/castxml-linux.tar.gz | tar zxf - -C ${HOME}; + fi; + fi + + # Add the castxml binary to the path + - if [[ $XML_GENERATOR == "castxml" ]]; then + export PATH=$PATH:~/castxml/bin/; + fi + + # Setup gccxml for the gccxml builds on linux + - if [[ "$XML_GENERATOR" == "gccxml" ]]; then sudo apt-get update -qq; fi + - if [[ "$XML_GENERATOR" == "gccxml" ]]; then sudo apt-get install -qq gccxml; fi + # Install pep8, needed by the unit tests - pip install pep8 + # Install coverage tools (On 3.2 the new coverage is broken, use an old one) # https://github.com/menegazzo/travispy/issues/20 - - if [ $TRAVIS_PYTHON_VERSION == 3.2 ]; - then pip install 'coverage<4.0'; else - pip install coverage; + - if [ $TRAVIS_PYTHON_VERSION == 3.2 ]; then + pip install 'coverage<4.0'; + else + pip install coverage; fi - pip install coveralls @@ -27,11 +87,23 @@ install: - if [[ $TRAVIS_PYTHON_VERSION == 2.6 ]]; then pip install unittest2; fi script: + - echo $TRAVIS_OS_NAME + # Modify sitecustomize.py file for coverage. Allows to cover files run in a subprocess. - - touch "/home/travis/virtualenv/python${TRAVIS_PYTHON_VERSION}/lib/python${TRAVIS_PYTHON_VERSION}/sitecustomize.py" - - printf "import coverage\ncoverage.process_startup()\n" > "/home/travis/virtualenv/python${TRAVIS_PYTHON_VERSION}/lib/python${TRAVIS_PYTHON_VERSION}/sitecustomize.py" + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then touch "/home/travis/virtualenv/python${TRAVIS_PYTHON_VERSION}/lib/python${TRAVIS_PYTHON_VERSION}/sitecustomize.py"; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ $TRAVIS_PYTHON_VERSION == 2 ]]; then touch "/usr/local/lib/python2.7/site-packages/sitecustomize.py"; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ $TRAVIS_PYTHON_VERSION == 3 ]]; then touch "/usr/local/lib/python3.5/site-packages/sitecustomize.py"; fi + + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; + then printf "import coverage\ncoverage.process_startup()\n" > "/home/travis/virtualenv/python${TRAVIS_PYTHON_VERSION}/lib/python${TRAVIS_PYTHON_VERSION}/sitecustomize.py"; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ $TRAVIS_PYTHON_VERSION == 2 ]]; + then printf "import coverage\ncoverage.process_startup()\n" > "/usr/local/lib/python2.7/site-packages/sitecustomize.py"; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ $TRAVIS_PYTHON_VERSION == 3 ]]; + then printf "import coverage\ncoverage.process_startup()\n" > "/usr/local/lib/python3.5/site-packages/sitecustomize.py"; fi + # Install pygccxml - python setup.py install + # Run the tests with coverage - coverage run unittests/test_all.py # Combine multiple .coverage files (we have multiple files because some scripts were run in a subprocess). From fc617ad605ba45dca5f8330cf08ed9b0b46f1317 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 12 Mar 2016 13:25:51 +0100 Subject: [PATCH 083/268] Increase recursion limit for python, needed to fix travis build error Three tests are failing in declarations_comparison_tester with: RecursionError: maximum recursion depth exceeded This is an attempt to fix it, it is not sure it will help. --- unittests/autoconfig.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/unittests/autoconfig.py b/unittests/autoconfig.py index 315d0504..ac8a00a8 100644 --- a/unittests/autoconfig.py +++ b/unittests/autoconfig.py @@ -8,6 +8,9 @@ import logging import warnings +# Prevents copy.deepcopy RecursionError in some tests (Travis build) +sys.setrecursionlimit(10000) + this_module_dir_path = os.path.abspath( os.path.dirname(sys.modules[__name__].__file__)) From 0db947dd9684c34ac16928200fec030a583a762d Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Sat, 12 Mar 2016 17:13:05 -0700 Subject: [PATCH 084/268] Fix unqualified enums in default arguments for CastXML CastXML currently doesn't modify enum names used in default arguments for functions, it simply uses the same text present in the source file. This causes compilation failures in bindings generated by pyplusplus in case of code such as the following: namespace ns1 { namespace ns2 { enum color { red }; void foo(color arg = ns2::red); } } In this case, CastXML produces "ns2::red" as the default value while GCCXML removes the namespace name and sets the default value to "red". pygccxml's patcher for unqualified names expects GCCXML's behavior, so it fails to detect the CastXML output as one needing further qualification. Consequently, pyplusplus refers to the default value as "ns2::red", which fails compilation because the name needs to be fully qualified as "ns1::ns2::red". This fix produces the desired qualified output from pygccxml with both GCCXML and CastXML. Change-Id: I724408981b69bc184e246636da3fac0c70cb215c --- pygccxml/parser/patcher.py | 8 +++-- unittests/data/patcher.hpp | 8 +++++ unittests/patcher_tester.py | 71 ++++++++++++++++++++----------------- 3 files changed, 52 insertions(+), 35 deletions(-) diff --git a/pygccxml/parser/patcher.py b/pygccxml/parser/patcher.py index a422042a..7d5c4865 100644 --- a/pygccxml/parser/patcher.py +++ b/pygccxml/parser/patcher.py @@ -44,14 +44,18 @@ def __is_unqualified_enum(self, func, arg): if not declarations.is_enum(type_): return False enum_type = declarations.enum_declaration(type_) - return enum_type.has_value_name(arg.default_value) + # GCCXML does not qualify an enum value in the default argument + # but CastXML does. Split the default value and use only the + # enum value for fixing it. + return enum_type.has_value_name( + arg.default_value.split('::')[-1]) def __fix_unqualified_enum(self, func, arg): type_ = declarations.remove_reference(declarations.remove_cv(arg.type)) enum_type = declarations.enum_declaration(type_) return self.__join_names( enum_type.parent.decl_string, - arg.default_value) + arg.default_value.split('::')[-1]) def __is_invalid_integral(self, func, arg): type_ = declarations.remove_reference(declarations.remove_cv(arg.type)) diff --git a/unittests/data/patcher.hpp b/unittests/data/patcher.hpp index 03f4d5eb..f0d20159 100644 --- a/unittests/data/patcher.hpp +++ b/unittests/data/patcher.hpp @@ -12,11 +12,19 @@ namespace ns1{ namespace ns2{ enum fruit{ apple, orange }; +void fix_enum2( fruit arg=apple ); } } void fix_enum( ns1::ns2::fruit arg=ns1::ns2::apple ); +namespace ns3{ + +using namespace ns1::ns2; +void fix_enum3( fruit arg=orange ); + +} + typedef unsigned long long ull; void fix_numeric( ull arg=(ull)-1 ); diff --git a/unittests/patcher_tester.py b/unittests/patcher_tester.py index 5047d2ef..029dfcf1 100644 --- a/unittests/patcher_tester.py +++ b/unittests/patcher_tester.py @@ -23,48 +23,53 @@ def __init__(self, architecture, *args): def test_enum_patcher(self): fix_enum = self.global_ns.free_fun("fix_enum") default_val = fix_enum.arguments[0].default_value - if "CastXML" in utils.xml_generator: - # Most clean output, no need to patch - self.assertTrue(default_val == "ns1::ns2::apple") - else: - self.assertTrue(default_val == "::ns1::ns2::apple") + self.assertEqual(default_val, "::ns1::ns2::apple") + + if 32 == self.architecture or "CastXML" in utils.xml_generator: + fix_enum2 = self.global_ns.free_fun("fix_enum2") + default_val = fix_enum2.arguments[0].default_value + self.assertEqual(default_val, "::ns1::ns2::apple") + + ns1 = self.global_ns.namespace("ns1") + ns2 = ns1.namespace("ns2") + fix_enum2 = ns2.free_fun("fix_enum2") + default_val = fix_enum2.arguments[0].default_value + self.assertEqual(default_val, "::ns1::ns2::apple") + + fix_enum3 = self.global_ns.free_fun("fix_enum3") + default_val = fix_enum3.arguments[0].default_value + self.assertEqual(default_val, "::ns1::ns2::orange") # double_call = declarations.find_declaration( # decls, type=declarations.free_function_t, name='double_call' ) def test_numeric_patcher(self): - fix_numeric = self.global_ns.free_fun("fix_numeric") + fix_numeric = self.global_ns.free_function("fix_numeric") if 32 == self.architecture: if "0.9" in utils.xml_generator: if platform.machine() == "x86_64": - self.assertTrue( - fix_numeric.arguments[0].default_value == "-1u", - fix_numeric.arguments[0].default_value) + self.assertEqual( + fix_numeric.arguments[0].default_value, "-1u") else: val = "0xffffffffffffffffu" - self.assertTrue( - fix_numeric.arguments[0].default_value == val, - fix_numeric.arguments[0].default_value) + self.assertEqual( + fix_numeric.arguments[0].default_value, val) else: val = "0xffffffffffffffff" - self.assertTrue( - fix_numeric.arguments[0].default_value == val, - fix_numeric.arguments[0].default_value) + self.assertEqual( + fix_numeric.arguments[0].default_value, val) else: if "CastXML" in utils.xml_generator: - # Most clean output, no need to patch - self.assertTrue( - fix_numeric.arguments[0].default_value == "(ull)-1", - fix_numeric.arguments[0].default_value) + self.assertEqual( + fix_numeric.arguments[0].default_value, "(ull)-1") else: - self.assertTrue( - fix_numeric.arguments[0].default_value == "0ffffffff", - fix_numeric.arguments[0].default_value) + self.assertEqual( + fix_numeric.arguments[0].default_value, "0ffffffff") def test_unnamed_enum_patcher(self): fix_unnamed = self.global_ns.free_fun("fix_unnamed") - self.assertTrue( - fix_unnamed.arguments[0].default_value == "int(::fx::unnamed)") + self.assertEqual( + fix_unnamed.arguments[0].default_value, "int(::fx::unnamed)") def test_function_call_patcher(self): fix_function_call = self.global_ns.free_fun("fix_function_call") @@ -72,33 +77,33 @@ def test_function_call_patcher(self): if "CastXML" in utils.xml_generator: # Most clean output, no need to patch val = "calc(1, 2, 3)" - self.assertTrue(default_val == val) + self.assertEqual(default_val, val) elif "0.9" in utils.xml_generator: val = "function_call::calc(1, 2, 3)" - self.assertTrue(default_val == val) + self.assertEqual(default_val, val) else: val = "function_call::calc( 1, 2, 3 )" - self.assertTrue(default_val == val) + self.assertEqual(default_val, val) def test_fundamental_patcher(self): fcall = self.global_ns.free_fun("fix_fundamental") val = "(unsigned int)(::fundamental::eggs)" - self.assertTrue( - fcall.arguments[0].default_value == val) + self.assertEqual( + fcall.arguments[0].default_value, val) def test_constructor_patcher(self): typedef__func = self.global_ns.free_fun("typedef__func") default_val = typedef__func.arguments[0].default_value if "0.9" in utils.xml_generator: val = "typedef_::original_name()" - self.assertTrue(default_val == val) + self.assertEqual(default_val, val) elif "CastXML" in utils.xml_generator: # Most clean output, no need to patch val = "typedef_::alias()" - self.assertTrue(default_val == val) + self.assertEqual(default_val, val) else: val = "::typedef_::alias( )" - self.assertTrue(default_val == val) + self.assertEqual(default_val, val) if 32 == self.architecture: clone_tree = self.global_ns.free_fun("clone_tree") default_values = [] @@ -116,7 +121,7 @@ def test_constructor_patcher(self): "std::allocator > > >((&allocator" + ", " + "std::allocator > >()))")] - self.assertTrue( + self.assertIn( clone_tree.arguments[0].default_value in default_values) From 309cab05a21bb24eb87fa2f5209c8b5f1ece5724 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 13 Mar 2016 23:01:22 +0100 Subject: [PATCH 085/268] Use the new is_union() type_traits when possible Also, remove commented out code in unnamed_classes.hpp file. The purpose is to have an anonymous union in the tests. --- pygccxml/declarations/function_traits.py | 7 ++++--- pygccxml/declarations/type_traits.py | 18 +++++++++--------- unittests/data/unnamed_classes.hpp | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/pygccxml/declarations/function_traits.py b/pygccxml/declarations/function_traits.py index 07fb99b3..3305b2cf 100644 --- a/pygccxml/declarations/function_traits.py +++ b/pygccxml/declarations/function_traits.py @@ -56,11 +56,12 @@ def is_same_return_type(f1, f2): return False if not type_traits.is_class(rt1) or not type_traits.is_class(rt2): return type_traits.is_same(rt1, rt2) + + if type_traits.is_union(rt1) or type_traits.is_union(rt2): + return type_traits.is_same(rt1, rt2) + c1 = type_traits.class_traits.get_declaration(rt1) c2 = type_traits.class_traits.get_declaration(rt2) - if c1.class_type == class_declaration.CLASS_TYPES.UNION \ - or c2.class_type == class_declaration.CLASS_TYPES.UNION: - return type_traits.is_same(rt1, rt2) return type_traits.is_same(c1, c2) \ or type_traits.is_base_and_derived(c1, c2) \ or type_traits.is_base_and_derived(c2, c1) diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index d28a31dc..21fbd0e8 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -972,25 +972,25 @@ def __is_noncopyable_single(class_): def is_noncopyable(class_): """returns True, if class is noncopyable, False otherwise""" logger = utils.loggers.cxx_parser - class_ = class_traits.get_declaration(class_) + class_decl = class_traits.get_declaration(class_) true_header = "is_noncopyable(TRUE) - %s - " % class_.decl_string # false_header = "is_noncopyable(false) - %s - " % class_.decl_string - if class_.class_type == class_declaration.CLASS_TYPES.UNION: + if is_union(class_): return False - if class_.is_abstract: + if class_decl.is_abstract: logger.debug(true_header + "abstract client") return True # if class has public, user defined copy constructor, than this class is # copyable - copy_ = class_.find_copy_constructor() + copy_ = class_decl.find_copy_constructor() if copy_ and copy_.access_type == 'public' and not copy_.is_artificial: return False - for base_desc in class_.recursive_bases: + for base_desc in class_decl.recursive_bases: assert isinstance(base_desc, class_declaration.hierarchy_info_t) if base_desc.related_class.decl_string in \ @@ -1022,17 +1022,17 @@ def is_noncopyable(class_): "__is_noncopyable_single returned True") return True - if not has_copy_constructor(class_): + if not has_copy_constructor(class_decl): logger.debug(true_header + "does not have trivial copy constructor") return True - elif not has_public_constructor(class_): + elif not has_public_constructor(class_decl): logger.debug(true_header + "does not have a public constructor") return True - elif has_destructor(class_) and not has_public_destructor(class_): + elif has_destructor(class_decl) and not has_public_destructor(class_decl): logger.debug(true_header + "has private destructor") return True else: - return __is_noncopyable_single(class_) + return __is_noncopyable_single(class_decl) def is_defined_in_xxx(xxx, cls): diff --git a/unittests/data/unnamed_classes.hpp b/unittests/data/unnamed_classes.hpp index 1e737558..b4b8a512 100644 --- a/unittests/data/unnamed_classes.hpp +++ b/unittests/data/unnamed_classes.hpp @@ -25,7 +25,7 @@ struct S1{ unsigned int raw; } flags; - union /*FileAttribs*/{ + union { struct{ unsigned int isReadOnly : 1; unsigned int isHidden : 1; From b21695189757d094fbf4713eb69f3bc67dafdb86 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 17 Mar 2016 23:10:18 +0100 Subject: [PATCH 086/268] find_xml_generator will now look for castxml first --- pygccxml/utils/utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index 5dd92d7e..18ea1f30 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -35,8 +35,8 @@ def find_xml_generator(name=None): :param name: name of the c++ parser: castxml or gccxml :type name: str - If no name is given the function first looks for gccxml, - then for castxml. If no c++ parser is found the function + If no name is given the function first looks for castxml, + then for gccxml. If no c++ parser is found the function raises an exception. """ @@ -47,11 +47,11 @@ def find_xml_generator(name=None): command = "which" if name is None: - name = "gccxml" + name = "castxml" p = subprocess.Popen([command, name], stdout=subprocess.PIPE) path = p.stdout.read().decode("utf-8") if path == "": - name = "castxml" + name = "gccxml" p = subprocess.Popen([command, name], stdout=subprocess.PIPE) path = p.stdout.read().decode("utf-8") else: From 12f012b1806fefe5608b9cd7ec00600b2e290aa6 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 19 Mar 2016 23:23:47 +0100 Subject: [PATCH 087/268] Remove duplicated import --- pygccxml/declarations/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 9016e547..f88f6473 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -27,8 +27,6 @@ from .class_declaration import class_declaration_t from .class_declaration import class_types -from .typedef import typedef_t - from .cpptypes import type_t from .cpptypes import dummy_type_t from .cpptypes import unknown_t From 6be8e48c104294c1a55a20f66d0dfeff144663fe Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Sun, 20 Mar 2016 12:52:31 -0600 Subject: [PATCH 088/268] Adapt patched output to CastXML cvs_revision 1.137 CastXML's output for default arguments for function parameters was modified in response to CastXML/CastXML#51. The tool now generates fully qualified names in default arguments, so we need to check the `cvs_revision` attribute in the XML output to differentiate between the different output formats. Change-Id: I18ee4d2319dd879e8b9a2d40bf6bee2d3ec1224e --- pygccxml/parser/scanner.py | 1 + pygccxml/utils/__init__.py | 1 + unittests/patcher_tester.py | 29 +++++++++++++++++++++-------- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index 50edd37e..ea279b7f 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -632,6 +632,7 @@ def __read_version(self, attrs): # compatibility. logger.debug('CASTXML version - None ( %s )', version_str) utils.xml_generator = declarations.xml_generators.CASTXML_None + utils.xml_output_version = version def __update_unnamed_class(self, decl, attrs): """ diff --git a/pygccxml/utils/__init__.py b/pygccxml/utils/__init__.py index cead420a..92bf0f72 100644 --- a/pygccxml/utils/__init__.py +++ b/pygccxml/utils/__init__.py @@ -20,3 +20,4 @@ # Version of xml generator which was used. xml_generator = None +xml_output_version = None diff --git a/unittests/patcher_tester.py b/unittests/patcher_tester.py index 029dfcf1..22676acf 100644 --- a/unittests/patcher_tester.py +++ b/unittests/patcher_tester.py @@ -60,34 +60,47 @@ def test_numeric_patcher(self): fix_numeric.arguments[0].default_value, val) else: if "CastXML" in utils.xml_generator: + if utils.xml_output_version >= 1.137: + val = "(unsigned long long)-1" + else: + val = "(ull)-1" self.assertEqual( - fix_numeric.arguments[0].default_value, "(ull)-1") + fix_numeric.arguments[0].default_value, val) else: self.assertEqual( fix_numeric.arguments[0].default_value, "0ffffffff") def test_unnamed_enum_patcher(self): fix_unnamed = self.global_ns.free_fun("fix_unnamed") + if ("CastXML" in utils.xml_generator and + utils.xml_output_version >= 1.137): + val = "fx::unnamed" + else: + val = "int(::fx::unnamed)" self.assertEqual( - fix_unnamed.arguments[0].default_value, "int(::fx::unnamed)") + fix_unnamed.arguments[0].default_value, val) def test_function_call_patcher(self): fix_function_call = self.global_ns.free_fun("fix_function_call") default_val = fix_function_call.arguments[0].default_value if "CastXML" in utils.xml_generator: - # Most clean output, no need to patch - val = "calc(1, 2, 3)" - self.assertEqual(default_val, val) + if utils.xml_output_version >= 1.137: + val = "function_call::calc(1, 2, 3)" + else: + val = "calc(1, 2, 3)" elif "0.9" in utils.xml_generator: val = "function_call::calc(1, 2, 3)" - self.assertEqual(default_val, val) else: val = "function_call::calc( 1, 2, 3 )" - self.assertEqual(default_val, val) + self.assertEqual(default_val, val) def test_fundamental_patcher(self): fcall = self.global_ns.free_fun("fix_fundamental") - val = "(unsigned int)(::fundamental::eggs)" + if ("CastXML" in utils.xml_generator and + utils.xml_output_version >= 1.137): + val = "fundamental::spam::eggs" + else: + val = "(unsigned int)(::fundamental::eggs)" self.assertEqual( fcall.arguments[0].default_value, val) From 98855f8fd37c9a797f52d20a0a6c7e56f514dbc2 Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Sun, 13 Mar 2016 14:55:02 -0600 Subject: [PATCH 089/268] Fix unqualified integral const in default arguments for CastXML CastXML, prior to XML output versin 1.137, didn't modify integral constant names used in default arguments for functions, it simply used the same text present in the source file. This causes compilation failures in bindings generated by pyplusplus in case of code such as the following: struct st { static int const DEFAULT = 0; void fun(int arg=DEFAULT); }; In this case, CastXML produced `DEFAULT` as the default value while GCCXML qualifies the name and sets the default value to `st::DEFAULT`. Consequently, pyplusplus refers to the default value as `DEFAULT`, which fails compilation because the name needs to be fully qualified as `st::DEFAULT`. This fix produces the desired qualified output from pygccxml with both GCCXML and CastXML. As of XML output version 1.137, CastXML now produces fully qualified names for default arguments. Change-Id: Ie22ae5e7e058743efcd986a44797005be8e9c891 --- pygccxml/parser/patcher.py | 22 +++++++++++++++ unittests/data/patcher.hpp | 14 ++++++++++ unittests/patcher_tester.py | 54 +++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/pygccxml/parser/patcher.py b/pygccxml/parser/patcher.py index 7d5c4865..de87e956 100644 --- a/pygccxml/parser/patcher.py +++ b/pygccxml/parser/patcher.py @@ -3,6 +3,7 @@ # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt +import re from pygccxml import utils from pygccxml import declarations @@ -109,6 +110,27 @@ def __fix_invalid_integral(self, func, arg): arg.default_value)) else: parent = parent.parent + + # check if we have an unqualified integral constant + # only do patching in cases where we have a bare variable name + c_var = re.compile("[a-z_][a-z0-9_]*", re.IGNORECASE) + m = c_var.match(arg.default_value) + if m: + parent = func.parent + while parent: + try: + found = parent.variable(arg.default_value, + recursive=False) + except declarations.matcher.declaration_not_found_t: + # ignore exceptions if a match is not found + found = None + if found: + if declarations.is_fundamental(arg.type): + return "%s" % self.__join_names( + found.parent.decl_string, + arg.default_value) + parent = parent.parent + return arg.default_value def __find_enum(self, scope, default_value): diff --git a/unittests/data/patcher.hpp b/unittests/data/patcher.hpp index f0d20159..cae233fb 100644 --- a/unittests/data/patcher.hpp +++ b/unittests/data/patcher.hpp @@ -62,6 +62,20 @@ namespace osg{ } +namespace ns1{ + +static int const DEFAULT_1 = 0; +struct st1{ + static long const DEFAULT_2 = 10; + void fun1( int arg1=DEFAULT_1, long=DEFAULT_2 ); +}; + +} + +static int const DEFAULT_1 = 20; +int fun2( int arg1=DEFAULT_1, int arg2=ns1::DEFAULT_1, long arg3=::ns1::st1::DEFAULT_2 ); + + /*struct default_arg_t{};*/ /*default_arg_t create_default_argument();*/ /*void double_call( default_arg_t x=create_default_argument() );*/ diff --git a/unittests/patcher_tester.py b/unittests/patcher_tester.py index 22676acf..297777d1 100644 --- a/unittests/patcher_tester.py +++ b/unittests/patcher_tester.py @@ -70,6 +70,60 @@ def test_numeric_patcher(self): self.assertEqual( fix_numeric.arguments[0].default_value, "0ffffffff") + def test_unqualified_integral_patcher(self): + if 32 != self.architecture and "CastXML" not in utils.xml_generator: + # For this check to be removed, patcher_tester_64bit.xml + # will need to be updated for GCCXML + return + + ns1 = self.global_ns.namespace("ns1") + st1 = ns1.class_("st1") + fun1 = st1.member_function("fun1") + if "CastXML" in utils.xml_generator: + if utils.xml_output_version >= 1.137: + val1 = "ns1::DEFAULT_1" + val2 = "ns1::st1::DEFAULT_2" + else: + val1 = "::ns1::DEFAULT_1" + val2 = "::ns1::st1::DEFAULT_2" + self.assertEqual( + fun1.arguments[0].default_value, val1) + self.assertEqual( + fun1.arguments[1].default_value, val2) + else: + self.assertEqual( + fun1.arguments[0].default_value, + "ns1::DEFAULT_1") + self.assertEqual( + fun1.arguments[1].default_value, + "ns1::st1::DEFAULT_2") + + fun2 = self.global_ns.free_fun("fun2") + self.assertEqual( + fun2.arguments[0].default_value, + "::DEFAULT_1") + if "CastXML" in utils.xml_generator: + if utils.xml_output_version >= 1.137: + val1 = "ns1::DEFAULT_1" + val2 = "ns1::st1::DEFAULT_2" + else: + # Before XML output version 1.137, the following two + # were unpatched and were identical to the text in + # matcher.hpp + val1 = "ns1::DEFAULT_1" + val2 = "::ns1::st1::DEFAULT_2" + self.assertEqual( + fun2.arguments[1].default_value, val1) + self.assertEqual( + fun2.arguments[2].default_value, val2) + else: + self.assertEqual( + fun2.arguments[1].default_value, + "ns1::DEFAULT_1") + self.assertEqual( + fun2.arguments[2].default_value, + "ns1::st1::DEFAULT_2") + def test_unnamed_enum_patcher(self): fix_unnamed = self.global_ns.free_fun("fix_unnamed") if ("CastXML" in utils.xml_generator and From e6708c60a707a559faf5c12050ba94bb55c01771 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 24 Mar 2016 23:17:42 +0100 Subject: [PATCH 090/268] Regroup ifs, indent pygccxml style --- pygccxml/parser/patcher.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/pygccxml/parser/patcher.py b/pygccxml/parser/patcher.py index de87e956..c39865c5 100644 --- a/pygccxml/parser/patcher.py +++ b/pygccxml/parser/patcher.py @@ -119,16 +119,14 @@ def __fix_invalid_integral(self, func, arg): parent = func.parent while parent: try: - found = parent.variable(arg.default_value, - recursive=False) + found = parent.variable( + arg.default_value, recursive=False) except declarations.matcher.declaration_not_found_t: # ignore exceptions if a match is not found found = None - if found: - if declarations.is_fundamental(arg.type): - return "%s" % self.__join_names( - found.parent.decl_string, - arg.default_value) + if found and declarations.is_fundamental(arg.type): + return "%s" % self.__join_names( + found.parent.decl_string, arg.default_value) parent = parent.parent return arg.default_value From 39b5c62231be9aa1f518fe0a626176c6400e50ac Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 26 Mar 2016 11:43:04 +0100 Subject: [PATCH 091/268] Add example which shows how to parse a string containing c++ code --- docs/examples.rst | 1 + docs/examples/parsing-string/example.py | 28 ++++++++++++++++++++++++ docs/examples/parsing-string/example.rst | 16 ++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 docs/examples/parsing-string/example.py create mode 100644 docs/examples/parsing-string/example.rst diff --git a/docs/examples.rst b/docs/examples.rst index 0563ec2a..5fad9692 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -9,6 +9,7 @@ First examples :maxdepth: 1 examples/parsing/example.rst + examples/parsing-string/example.rst examples/variables/example.rst examples/searching1/example.rst examples/searching/example.rst diff --git a/docs/examples/parsing-string/example.py b/docs/examples/parsing-string/example.py new file mode 100644 index 00000000..8a32c841 --- /dev/null +++ b/docs/examples/parsing-string/example.py @@ -0,0 +1,28 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +from pygccxml import utils +from pygccxml import declarations +from pygccxml import parser + +# Find the location of the xml generator (castxml or gccxml) +generator_path, generator_name = utils.find_xml_generator() + +# Configure the xml generator +xml_generator_config = parser.xml_generator_configuration_t( + xml_generator_path=generator_path, + xml_generator=generator_name) + +# Write a string containing some c++ code +code = """ + class MyClass { + int a; + }; +""" + +# Parse the code +decls = parser.parse_string(code, xml_generator_config) + +# Get access to the global namespace +global_ns = declarations.get_global_namespace(decls) diff --git a/docs/examples/parsing-string/example.rst b/docs/examples/parsing-string/example.rst new file mode 100644 index 00000000..9f3f5f26 --- /dev/null +++ b/docs/examples/parsing-string/example.rst @@ -0,0 +1,16 @@ +================================ +Parsing a string containing code +================================ + +This example shows how to setup pygccxml to parse a string containing c++ code, +and how to access the declaration tree. Often, pygccxml is used to parse files +containing code, but there may be reasons to parse a string (for example +for debugging purposes). + +The following code will show you how to create a configuration for +the xml generator (an external tool, either castxml or gccxml), +and how to parse the string containing the c++ code: + +.. literalinclude:: example.py + :language: python + :lines: 5- From 2ddf0aa60eb67a4bfe0ee6754c7e639414bda32c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 28 Mar 2016 12:19:16 +0200 Subject: [PATCH 092/268] Add a trusty build and a trusty + gcc5 build --- .travis.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.travis.yml b/.travis.yml index 2e63a846..c783db57 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,24 @@ matrix: - os: linux python: 3.5 env: XML_GENERATOR="castxml" + - os: linux + dist: trusty + sudo: required + python: 3.5 + env: XML_GENERATOR="castxml" + - os: linux + dist: trusty + sudo: required + python: 3.5 + env: + - XML_GENERATOR="castxml" + - COMPILER=g++-5 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-5 - os: osx osx_image: xcode7.2 language: generic From 1d81d00170868d7be94a3442fe064dcf73e362e0 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 29 Mar 2016 22:06:26 +0200 Subject: [PATCH 093/268] Patch compiler path on the fly for gcc5 testing --- .travis.yml | 5 +++++ unittests/autoconfig.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c783db57..88d764d5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -89,6 +89,11 @@ before_install: - if [[ "$XML_GENERATOR" == "gccxml" ]]; then sudo apt-get update -qq; fi - if [[ "$XML_GENERATOR" == "gccxml" ]]; then sudo apt-get install -qq gccxml; fi + # Patch the compiler path on the fly for gcc5 testing + - if [[ "$COMPILER" == "g++-5" ]] && [[ $XML_GENERATOR == "castxml" ]]; then + cd unittests && sed -i s%compiler=None%compiler=\"/usr/bin/g++-5\"%g autoconfig.py; + fi + # Install pep8, needed by the unit tests - pip install pep8 diff --git a/unittests/autoconfig.py b/unittests/autoconfig.py index ac8a00a8..e8867dbc 100644 --- a/unittests/autoconfig.py +++ b/unittests/autoconfig.py @@ -46,7 +46,7 @@ class cxx_parsers_cfg(object): 'xml_generator.cfg', xml_generator_path=generator_path, working_directory=data_directory, - compiler=pygccxml.utils.native_compiler.get_gccxml_compiler(), + compiler=None, xml_generator=generator_name) if generator_name == 'gccxml': From f097d52b1e2fe647d98fc38af87b39d45bb7ea49 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 29 Mar 2016 22:26:43 +0200 Subject: [PATCH 094/268] Go back one level after the sed command --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 88d764d5..4a0ff147 100644 --- a/.travis.yml +++ b/.travis.yml @@ -91,7 +91,7 @@ before_install: # Patch the compiler path on the fly for gcc5 testing - if [[ "$COMPILER" == "g++-5" ]] && [[ $XML_GENERATOR == "castxml" ]]; then - cd unittests && sed -i s%compiler=None%compiler=\"/usr/bin/g++-5\"%g autoconfig.py; + cd unittests && sed -i s%compiler=None%compiler=\"/usr/bin/g++-5\"%g autoconfig.py && cd ..; fi # Install pep8, needed by the unit tests From 4fcf207cb776f851fb723c9e9985e4c8b208ee8a Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 29 Mar 2016 22:52:30 +0200 Subject: [PATCH 095/268] Add a precise (12.04) build with gcc 5.2.1 --- .travis.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4a0ff147..0de575b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,18 @@ matrix: - os: linux python: 3.5 env: XML_GENERATOR="castxml" + - os: linux + python: 3.5 + env: + - XML_GENERATOR="castxml" + - COMPILER=g++-5 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + # This will be gcc 5.2.1 + - g++-5 - os: linux dist: trusty sudo: required @@ -44,6 +56,7 @@ matrix: sources: - ubuntu-toolchain-r-test packages: + # This will be gcc 5.3.0 - g++-5 - os: osx osx_image: xcode7.2 From f607a38d37d83d9e22bcd3d1534a0dd2e8b07912 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 3 Apr 2016 22:36:27 +0200 Subject: [PATCH 096/268] Update documentation: we are now using readthedocs --- docs/documentation.rst | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/docs/documentation.rst b/docs/documentation.rst index 09aa7f9e..726c40a9 100644 --- a/docs/documentation.rst +++ b/docs/documentation.rst @@ -12,35 +12,5 @@ in the root folder: This will build the documentation locally in the docs/_build/html folder. -Updating the documentation on github ------------------------------------- - -This is for the pygccxml maintainers. You need to have push access to the -github repository to do this. - -The documentation is hosted on github through the github pages service. -You can find it at http://gccxml.github.io/pygccxml/ - -To update the documentation, run the following command in the root folder. - - make gh-pages - -You can find more details in the Makefile about this command. It will -checkout to the gh-pages branch, build the documentation, update the -html files in the documentation folder. Then it will automatically commit the -changes. You will then have time to review the changes and push them to -origin/gh-pages. - -This script was setup and adapted from here: -http://blog.nikhilism.com/2012/08/automatic-github-pages-generation-from.html - -Moving to a new version of sphinx ---------------------------------- - -If you update the docs with "make gh-pages", and the sphinx version you use -is different than the previously used one, this will result in many changes -in the files due to the version change. To prevent this, a version check -was added in the sphinx Makefile in the root directory. - -When you are ready for a sphinx update, you need to update the needed version -number in the Makefile and commit this change. +For each commit on the master and develop branches, the documentation is +automatically built and can be found here: https://readthedocs.org/projects/pygccxml/ From a81211a408edd9d1b338348c4187e3cd7bdf6dbc Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 3 Apr 2016 22:55:46 +0200 Subject: [PATCH 097/268] Rename download.rst to install.rst, cleanup documentation --- docs/download.rst | 44 -------------------------------------------- docs/index.rst | 14 ++++---------- docs/install.rst | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 54 deletions(-) delete mode 100644 docs/download.rst create mode 100644 docs/install.rst diff --git a/docs/download.rst b/docs/download.rst deleted file mode 100644 index c6ecf88c..00000000 --- a/docs/download.rst +++ /dev/null @@ -1,44 +0,0 @@ -================== -Download & Install -================== - ------------------- -pygccxml on Github ------------------- - -The pygccxml project is hosted on Github. Using Github you can: - -1) get access to the source code -2) create pull requests -3) report bugs or ask for new features - ------------- -Installation ------------- - -Note that you will need `GCC-XML`_ on your system, see section below. - -You can use pip to install pygccxml: - - pip install pygccxml - -To install from source, you can use the usual procedure: - - python setup.py install - -------- -GCC-XML -------- -There are few different ways to install `GCC-XML`_ on your system: - -1. If you use Linux, than I am almost sure your system provides the "gccxml" package. - Consider to install it using "native"(rpm, deb, portage) packaging system. - -.. line separator - -2. Another option is to install it from the source code. See `instructions`_ - provided by Brad King, the author of `GCC-XML`_. Installation from sources - is supported for Windows, Linux and Mac platforms. - -.. _`instructions` : http://gccxml.org/HTML/Install.html -.. _`GCC-XML`: http://www.gccxml.org diff --git a/docs/index.rst b/docs/index.rst index 84d35a84..b78683a8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,16 +12,10 @@ Using `pygccxml` you can: * Build code analyzers * ... -Installing -========== - -You can use pip to install pygccxml:: - - pip install pygccxml - -To install from source, you can use the usual procedure:: +Installation +============ - python setup.py install +Installation instructions can be found here: :doc:`Installation ` Examples ======== @@ -55,7 +49,7 @@ Documentation contents .. toctree:: :maxdepth: 1 - download + install examples documentation query_interface diff --git a/docs/install.rst b/docs/install.rst new file mode 100644 index 00000000..0a47758a --- /dev/null +++ b/docs/install.rst @@ -0,0 +1,38 @@ +Download & Install +================== + +Prerequisite: CastXML +--------------------- + +You need to have `CastXML`_ installed. + +Installation of pygccxml +------------------------ + +You can use pip to install pygccxml: + + pip install pygccxml + +To install from source, you can use the usual procedure: + + python setup.py install + +GCC-XML (Legacy) +---------------- + +These instructions are only here for historical reasons; `pygccxml` is now using +`CastXML` by default. + +There are few different ways to install `GCC-XML`_ on your system: + +1. If you use Linux, than I am almost sure your system provides the "gccxml" package. + Consider to install it using "native"(rpm, deb, portage) packaging system. + +.. line separator + +2. Another option is to install it from the source code. See the `instructions`_ here. + Installation from sources supported for Windows, Linux and Mac platforms. + +.. _`instructions` : http://gccxml.org/HTML/Install.html +.. _`GCC-XML`: http://www.gccxml.org +.. _`CastXML`: https://github.com/CastXML/CastXML From 58a48ea63a3bbc2e07fcfb6349ed306f856e0a53 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 3 Apr 2016 22:58:38 +0200 Subject: [PATCH 098/268] Remove unused links; update test environment description --- docs/index.rst | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index b78683a8..432da9b9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -38,9 +38,9 @@ License Test environment ================ -`pygccxml` comes with comprehensive unit tests. They are executed on the `Ubuntu`_ Linux operating systems. -See the `Travis`_ builds for more details. `pygccxml` is tested under python 2.6, 2.7, 3.2, 3.3 and 3.4. -All in all, `pygccxml` has more than 230 tests. +`pygccxml` comes with comprehensive unit tests. They are executed on different operating systems, +and with different versions of compilers. See the `Travis`_ builds for more details. +`pygccxml` is tested under python 2.6, 2.7, 3.2, 3.3, 3.4, 3.5. All in all, `pygccxml` has more than 230 tests. Documentation contents @@ -62,13 +62,7 @@ Documentation contents credits apidocs/api -.. _`WSDL`: http://www.w3.org/TR/wsdl -.. _`SourceForge`: http://sourceforge.net/index.php -.. _`Docutils`: http://docutils.sourceforge.net -.. _`Python`: http://www.python.org -.. _`GCC-XML`: http://www.gccxml.org .. _`Boost Software License`: http://boost.org/more/license_info.html -.. _`Ubuntu`: http://www.ubuntu.com/ .. _`Travis`: https://travis-ci.org/gccxml/pygccxml/builds .. _`boost::type_traits` : http://www.boost.org/libs/type_traits/index.html From c042d09adff9922c12fb2ab6cebc8dc6ac590c36 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 5 Apr 2016 23:53:55 +0200 Subject: [PATCH 099/268] Create a real CHANGELOG.md file, extracted from the history page --- CHANGELOG.md | 840 ++++++++++++++++++++++++++++++++++++++++++++++ docs/history.rst | 846 +---------------------------------------------- 2 files changed, 844 insertions(+), 842 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..89f9c817 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,840 @@ +Changes +======= + +Version 1.7.3 +------------- + +1. Addition of an is_union() method in the type_traits module. + +2. type_traits.smart_pointer_traits will now classify std::shared_ptr as a + smart pointer (only boost::shared_ptr was recognized before) + +3. Fix a regression in undname_creator_t.format_argtypes + +4. C++xx flags are now correctly passed to CastXML. Allowed flags are: + "-std=c++98", "-std=c++03", "-std=c++11", "-std=c++14", "-std=c++1z" + Thanks to Mark Moll for the fix. + +5. Add better support for "typedef (class|struct) {} foo;" syntax when using + CastXML. GCCXML did not recognize the typedef. Fetching these + declarations can now be done with: .typedef("foo") or .class_("foo"). + +6. Add support for the future llvm 3.9. As in release v1.7.1, new structs and + typedefs are now exposed by llvm, which broke pyplusplus. + In this case these are ```__NSConstantString_tag``` and ```__NSConstantString```. + The two declarations are now hidden from the declarations tree, but can still + be generated by using the ``config.flags = ["f1"]`` option. + +7. Multiple fixes to adapt default arguments in functions for py++. Using the + latest version of CastXML is recommended. This makes sure default arguments + for function parameters are correctly defined, so that py++ can process them. + +8. Fix for exception when using castxml + gcc5 + std=c++11 and maps. + +9. Removed unittest2 dependency for testing with python 2.6 + +10. Testing: test with std::tr1 unordered containers for gcc >= 4.4.7 and castxml + +11. Cosmetic fix for generator name printed to stdout when launching unit tests + +12. Fix simple typo in example.py comment + +Thanks to the following people for their contribution to this release: +Mark Moll, Ashish Sadanandan, Mark Oates + +Version 1.7.2 +------------- + +1. Fix exception in is_copy_constructor when the constructor's argument was + a typedef. is_copy_constructor will now return False instead of failing. + See issue #27. + +2. Fix bug with utils.xml_generator being unset when reading cached file. + This could for example happen when reading a cached file from a second + python interpreter (e.g. in a subprocess or by calling pygccxml + multiple times from a script). See issue #27. + +3. SafeConfigParser is throwing a deprecation warning in python 3.2 and newer. + Use ConfigParser instead. Thanks to Mark Moll for the patch. + +4. Add support for cflags property in config files. + Thanks to Mark Moll for the patch. + +Version 1.7.1 +------------- + +1. Remove the __va_list_tag declaration from the tree when parsing with CastXML + + The __va_list_tag declarations are internal declarations, which are often + not needed. They are for example polluting the declarations tree when running + pyplusplus. + + This is optional but on by default. To still load the __va_list_tag declarations + in the tree, a config flag can be set like this: ``config.flags = ["f1"]``, + or by passing the ``flags=["f1"]`` argument the config setup. + +2. Some code cleanup + +3. Build new package for pypi. The ``1.7.0`` upload has gone wrong ... + + +Version 1.7.0 +------------- + +1. Added support for CastXML (https://github.com/CastXML/CastXML) + + GCCXML is deprecated and does no more work with modern compilers. + CastXML should be used instead. + + ``pygccxml 1.7.0`` is still compatible with GCCXML and no changes are needed for people working with GCCXML. + +2. [CastXML] A new function was introduced to help find which XML generator you are using. + + If the generator (GCCXML or CastXML) is in your path, it will be detected. + + .. code-block:: python + + generator_path, generator_name = pygccxml.utils.find_xml_generator() + +3. [CastXML] When using the configuration, you will need to tell pygccxml which xml generator you are using. + + .. code-block:: python + + xml_generator_config = parser.xml_generator_configuration_t( + xml_generator_path=generator_path, + xml_generator=generator_name, + ) + + ``gccxml_configuration_t`` is an alias of ``xml_generator_configuration_t``. + + ``load_gccxml_configuration`` is an alias of ``load_xml_generator_configuration``. + + Both can still be used but will be deprecated. + +4. [CastXML] The compiler path can be passed to castxml. + + This is done by using the ``compiler_path`` attribute in the configuration. + Note that this may be important because the resulting xml file is slightly different + depending on the compiler. + +5. [CastXML] Added support for some fields which have no location. + + These fields are: ``gp_offset``, ``fp_offset``, ``overflow_arg_area``, ``reg_save_area`` + +6. [CastXML] Mangled names are only available for functions and variables with CastXML. + + Getting the mangled attribute on a ``declaration`` will fail. + +7. [CastXML] Demangled names are not available. + + Getting a demangled name will fail. + +8. [CastXML] Add new container traits: + + ``unordered maps``, ``unordered sets``, ``multimaps``, ``multisets`` + +9. [CastXML] Annotations: + + Instead of using the ``__attribute((gccxml("string")))`` c++ syntax (see version 0.9.5), the ``__attribute__ ((annotate ("out")))`` can now be used to annotate code with CastXML. + +10. [CastXML] Disabled relinking of: + + .. code-block:: python + + rebind, void *> > + + This made the ``find_container_traits_tester`` unit tests fail with ``CastXML``. + This class defintion is present in the clang AST tree, but I don't know why it is + usefull. Please tell me if you need it so we can re-enable that featur in pygccxml. + +11. [Misc] Deprecated the ``compiler`` attribute and replaced it with a global ``utils.xml_generator`` variable. + + The ``compiler`` attribute was misleading; it was sometimes confused with the name and version of the xml generator. + + This change also fixes some internal problems with the algorithms cache. + +12. [Misc] ``declarations.has_trivial_copy`` was defintevely removed. + + Please use ``declarations.has_copy_constructor``. + + This was deprecated since version 0.9.5. + +13. [Misc] Remove ``gccxml`` logger from logger class (was deprecated). + + Please use ``cxx_parser`` instead. + +14. [Misc] Removed ``gccxml_runtime_error_t`` class. This was only used internally. + + Please use a normal ``RuntimeError`` instead. + +15. [Misc] Documentation was moved to readthedocs.org + + https://readthedocs.org/projects/pygccxml/ + +16. [Misc] Add quantifiedcode check + + https://www.quantifiedcode.com/app/project/117af14ef32a455fb7b3762e21083fb3 + +17. [Misc] Add option to keep xml files after errors, which is useful for debugging purposes. + +18. [Misc] Fix new pep8 warnings, clean up and simplify some code and comments + +19. [Misc] The compiler version debugging message is now hidden (closes #12) + +20. [Misc] Print less line separations in ``decl_printer``; this makes the output more compact. + +21. [Tests] Add new test for the ``contains_parent_dir`` function. + +22. [Tests] Add test for non copyable class with const class + +23. [Tests] Add test case for non copyable class due to const array + +24. [Doc] Small documentation update, moved people list to credits page, added new examples. + +25. [Misc] Add Travis unit tests for Python 3.5 + + +Version 1.6.2 +------------- + +1. Use setuptools instead of distutils for the packaging + +2. Change rights of declarations_cache.py and templates_tester.py + from -rwxr-xr-x+ to -rw-r--r--+, so that all the files have the same + execution rights. + +Version 1.6.1 +------------- + +1. Fix a regression introduced by previous changes. Syntax errors were introduced + in the part were you can check if a class is copyable or not (see #13). These + have been fixed now. + +Version 1.6 +----------- + +1. Moved the repository from mercurial to git + +2. Changed the documentation from epydoc to sphinx doc + +3. Setup the documentation as gh-page and add script to update the documentation + Just call "make gh-pages" on the root folder to create a commit with the + new documentation, which you may then push to the github repository. + The url for the documentation is now http://gccxml.github.io/pygccxml/ + +4. Add Travis unit tests for Python 2.6, 2.7, 3.2, 3.3 and 3.4 + The tests are run after each commit (see .travis.yml file in root folder) + https://travis-ci.org/gccxml/pygccxml + +5. Add automatic code coverage. The code coverage is run during each travis + run and the results are uploaded to https://coveralls.io/r/gccxml/pygccxml + +6. Fix copy_constructor unit test + +7. Deprecate parser.config_t (replaced by parser.gccxml_configuration_t) + +8. Fix for string comparison with future unicode literals + When using from __future__ import unicode_literals in python 2.7, + the call to the namespace() method would fail due to the isinstance/str + check. + + A is_str() function was added to the utils module, allowing for a + python 2 and python 3 compatible string check. + A unit test for this case was added. + +9. All the code is now pep8 compliant and is tested for this in an unit test + +10. Most of unused imports and variables were removed using the pyflakes tool + +11. Use new style python decorators (@property) everywhere + +12. Add new unit test for the example.py file + +13. Update the licence headers to reflect the change in maintainers + +Version 1.5.2 +------------- + +1. Make python 3.x compatible. Still works with python 2.6 and python 2.7. + +2. Add .dylib parser for Darwin + +3. Fix some unit tests + +4. workaround for problem with boost >=1.54 + +5. Simpler way of checksumming files in a python 2 and 3 compatible way + +6. Prevent warnings to be treated as fatal errors in py++ + +7. "has_inline" property was added to ``declarations.calldef_t`` class. + +8. Thanks to Aron Xu, for pointing out that it is better to use "os.name", + instead of "sys.platform" for platform specific logic. + +9. "__int128_t" and "__uint128_t" types were introduced. Many thanks to Gustavo Carneiro + for providing the patch. + +Version 1.5.1 +------------- + +1. adding problematic use case, contributed by Zbigniew Mandziejewicz + +2. Adding "explicit" attribute to constructor_t class + +3. "List symbols" (`nm`) utility invocation was improved and now handles + right relative paths and paths with spaces. Many thanks to Alejandro Dubrovsky + for providing the patch. + +4. Fix for "get dependencies" functionality + +5. Allow the process to continue, even in case the binary parser can not find the relevant declaration + +6. Fix bug related to merging free functions + +7. Improve decl_printer - sort declarations before printing + +8. Added new tests and ported tests to x86_64 architecture + +Version 1.5.0 +------------- + +1. Fix small bug in matcher - don't match namespaces by their location + +2. Documentation update and cleanup. (using sphinx-doc now). + +3. Fixing small bug on Windows, related to parsing configuration file + +4. Update setup.py + +5. fix 2779781 bug( pygccxml reverses array dimensions ) + +Note about version numbers before 1.5.0 +--------------------------------------- + +When the project moved from svn to git, versions were tagged from 1.0.0 on. +Note that there was no 1.2, 1.3 nor 1.4 version (this is maybe due to the +many forks and the slow down of the maintenance effort). + +Version 1.1.0 +------------- + +1. bsc and mspdb packages were deprecated + +2. Adding new functionality and improving initial environment handling + +3. Adding ability to dump exported classes + +4. Added more tests + +5. Add handling for "C" functions + +6. Fix bug "pygccxml parses const volatile variable args as just const" + +7. Rename bparser to binary_parsers + +8. Adding .so file parser + +9. Replace md5 with hashlib module (removes deprecation warnings) + +Version 1.0 +----------- + +1. Support for ellipsis was added. + + Warning: this feature introduce backward compatibility problem! + + Description: + + .. code-block:: c++ + + void do_smth( int, ... ) + + Before this change, pygccxml would report that the function ``do_smth`` has + only one argument. + + After this change, pygccxml will report that the function has two arguments. + The second argument type will be ``declarations.ellipsis_t``. All classes, + which describe callables, have new property ``has_ellipsis``. It the value of + the property is ``True``, than the function has ellipsis in its definition. + +2. New experimental back-end, based on ``.pdb`` (progam database file), was added. + +3. New high-level API wrapper for ``.bsc`` (browse source code file) was added. + +4. The recomended GCC_XML version to use with this release is CVS revision 123. + This revision introduces small, but very important feature. GCC_XML + started to dump artificial declarations (constructor, destructor, operator=). + ``pygccxml.declarations.type_traits`` functions were updated to use the new + information. + +5. ``declarations.decl_printer_t`` class dumps almost all available information + about a declaration. + +6. ``declarations.is_same_function`` was fixed and now it treats + "covariant returns" right. + +7. Search algorithm was improved for template instantiated classes. From + now, a spaces within the class name doesn't matter. + +8. pygccxml unit tests functionality was improved. Many thanks to Gustavo Carneiro. + +Version 0.9.5 +------------- + +1. Class ``free_operator_t`` is now able to provide references to the class declarations + instances it works on. + +2. Support for `GCC-XML attributes`_ was added. Many thanks to Miguel Lobo for + the implementation. + +.. _`GCC-XML attributes`: http://www.gccxml.org/HTML/Running.html + +3. A bug in parsing a function exception specification was fixed. Many thanks to + Jeremy Sanders. + +4. Support for a type/class "align", "offset" and "size" was added. Many thanks to + Ben Schleimer for the implementation. + +5. Support for GCC-XML 0.9 was added. + +6. Support for ``__restrict__`` was added. + +7. ``declarations.has_trivial_copy`` was renamed to ``declarations.has_copy_constructor``. + The old name is still available, but will be removed soon. + +8. ``declarations.priority_queue`` was renamed to ``declarations.priority_queue_traits``. + +9. ``declarations.find_container_traits`` function was added. + +10. Support for "partial name" was added. "Partial name" is the class name, without + template default arguments. The functionality was added to std containers + classes. + +11. ``declarations.class_t`` and ``declarations.class_declaration_t`` has new property - + ``container_traits``. This property describes std container element class. + +12. All logging is now done to ``stderr`` instead of ``stdout``. + +Version 0.9.0 +------------- + +1. Performance was improved. pygccxml is now 30-50% faster. The improvement + was achieved by using `cElementTree`_ package, ``iterparse`` functionality, + instead of standard XML SAX API. If `cElementTree`_ package is not available, + the built-in XML SAX package is used. + +.. _`cElementTree` : http://effbot.org/zone/celementtree.htm + +2. ``is_base_and_derived`` function was changed. The second argument could be + a tuple, which contains classes. The function returns ``True`` if at least one + class derives from the base one. + +.. line separator + +3. Class ``calldef_t`` has property - ``does_throw``. It describes + whether the function throws any exception or not. + +.. line separator + +4. Bug fixes: small bug was fixed in functionality that corrects GCC-XML reported + function default arguments. Reference to "enum" declaration extracted properly. + Many thanks to Martin Preisler for reporting the bug. + +.. line separator + +5. New type traits have been added: + + + * ``is_std_ostream`` + * ``is_std_wostream`` + +.. line separator + +6. C++ does not define implicit conversion between an integral type and ``void*``. + ``declarations.is_convertible`` type traits was fixed. + +.. line separator + +7. ``declarations.is_noncopyable`` type traits implementation was slightly changed. + Now it checks explicitly that class has: + + * default constructor + * copy constructor + * ``operator=`` + * destructor + + If all listed functions exist, than the algorithm returns ``False``, otherwise + it will continue to execute previous logic. + +.. line separator + +8. ``declarations.class_declaration_t`` has new property - ``aliases``. This is + a list of all aliases to the class declaration. + +.. line separator + +9. The message of the exception, which is raised from ``declarations.mdecl_wrapper_t`` + class was improved and now clearly explains what the problem is. + +.. line separator + +Version 0.8.5 +------------- + +1. Added new functionality: "I depend on them". Every declaration can report + types and declarations it depends on. + +2. ``signed char`` and ``char`` are two different types. This bug was fixed and + now pygccxml treats them right. Many thanks to Gaetan Lehmann for reporting + the bug. + +3. Declarations, read from GCC-XML generated file, could be saved in cache. + +4. New type traits have been added: + + * ``is_bool`` + +5. Small improvement to algorithm, which extracts ``value_type`` + ( ``mapped_type`` ) from "std" containers. + +6. Few aliases to long method name were introduced: + + ================================= ========================== + Name Alias + ================================= ========================== + ``scopedef_t.variable`` ``scopedef_t.var`` + ``scopedef_t.variables`` ``scopedef_t.vars`` + ``scopedef_t.member_function`` ``scopedef_t.mem_fun`` + ``scopedef_t.member_functions`` ``scopedef_t.mem_funs`` + ``scopedef_t.free_function`` ``scopedef_t.free_fun`` + ``scopedef_t.free_functions`` ``scopedef_t.free_funs`` + ================================= ========================== + +7. Fixing bug related to array size and cache. + +Version 0.8.2 +------------- + +1. Few small bug fix and unit tests have been introduced on 64 Bit platforms. + Many thanks to Gottfried Ganssauge! He also help me to discover and fix + some important bug in ``type_traits.__remove_alias`` function, by introducing + small example that reproduced the error. + +2. Huge speed improvement has been achieved (x10). Allen Bierbaum suggested to + save and reuse results of different pygccxml algorithms: + + * ``declarations.remove_alias`` + * ``declarations.full_name`` + * ``declarations.access_type`` + * ``declarations.demangled_name`` + * ``declarations.declaration_path`` + +3. Interface changes: + + * ``declarations.class_t``: + + + ``set_members`` method was removed + + + ``adopt_declaration`` method was introduced, instead of ``set_members`` + + * ``declarations.array_t`` class "set" accessor for size property was added. + + * ``declarations.namespace_t.adopt_declaration`` method was added. + + * ``declarations.variable_t.access_type`` property was added. + +4. New type traits have been added: + + * ``is_same_function`` + +5. Few bug were fixed. + +6. Documentation was improved. + +Version 0.8.1 +------------- + +1. pygccxml has been ported to MacOS X. Many thanks to Darren Garnier! + +2. New type traits have been added: + + * ``enum_traits`` + + * ``class_traits`` + + * ``class_declaration_traits`` + + * ``is_std_string`` + + * ``is_std_wstring`` + + * ``remove_declarated`` + + * ``has_public_less`` + + * ``has_public_equal`` + + * ``has_public_binary_operator`` + + * ``smart_pointer_traits`` + + * ``list_traits`` + + * ``deque_traits`` + + * ``queue_traits`` + + * ``priority_queue`` + + * ``vector_traits`` + + * ``stack_traits`` + + * ``map_traits`` + + * ``multimap_traits`` + + * ``hash_map_traits`` + + * ``hash_multimap_traits`` + + * ``set_traits`` + + * ``hash_set_traits`` + + * ``multiset_traits`` + + * ``hash_multiset_traits`` + +3. ``enumeration_t`` class interface was changed. Enumeration values are kept + in a list, instead of a dictionary. ``get_name2value_dict`` will build for + you dictionary, where key is an enumeration name, and value is an enumeration + value. + + This has been done in order to provide stable order of enumeration values. + +4. Now you can pass operator symbol, as a name to query functions: + + .. code-block:: python + + cls = global_namespace.class_( 'my_class' ) + op = cls.operator( '<' ) + #instead of + op = cls.operator( symbol='<' ) + +5. pygccxml improved a lot functionality related to providing feedback to user: + + * every package has its own logger + + * only important user messages are written to ``stdout`` + + * user messages are clear + +6. Support to Java native types has been added. + +7. It is possible to pass an arbitrary string as a parameter to GCC_XML. + +8. Native java types has been added to fundamental types. + +9. Cache classes implementation was improved. + +10. Few bug were fixed. + +11. Documentation was improved. + +12. ``mdecl_wrapper_t.decls`` property was renamed to ``declarations``. + The reason is that the current name ( ``decls`` ) conflicts with the method + of the same name in the decl interface from ``declarations.scopedef_t`` class. + + So for example: + + .. code-block:: python + + classes = ns.decls("class") + classes.decls("method") + + This will fail because it finds the attribute decls which is not a callable. + +Version 0.8 +----------- + +1. pygccxml now has power "select" interface. Read more about this cool feature + in tutorials. + +2. Improved support for template instantiations. pygccxml now take into + account demangled name of declarations. Please refer to documentation for + more explanantion. + +3. ``dummy_type_t`` - new type in types hierarchy. This is a very useful class + for code generation projects. + +4. New function - ``get_global_namespace``. As you can guess, it will find and + return reference to global namespace. + +5. New functionality in ``type_traits`` - ``has_public_assign``. This function + will return True, if class has public assign operator. + +6. ``declarations.class_t`` has new property - ``aliases``. This is a list of + all class aliases. + +7. Bug fixes. + +8. Documentation has been updated/written/improved. + +Version 0.7.1 +------------- + +**Attention - this going to be last version that is tested with Python 2.3** + +1. New fundamental types has been added + + * complex float + + * complex double + + * complex long double + +2. **Attention - non backward compatible change** + + ``declarations.filtering.user_defined`` and ``declarations.filtering.by_location`` + implementation has been changed. In previous version of those functions, + ``decls`` list has been changed in place. This was wrong behavior. Now, + those functions will return new list, which contains all desired declarations. + +3. Few new type traits has been added + + * *type_traits.has_destructor* + + * *type_traits.has_public_destructor* + + * *type_traits.has_public_constructor* + + * *type_traits.is_noncopyable* + +4. ``decl_printer_t`` class and ``print_declarations`` function have been added. + Now you can print in a nice way your declaration tree or part of it. + Thanks to Allen Bierbaum! + +5. New class ``declarations.decl_factory_t`` has been added. This is a default + factory for all declarations. From now all relevant parser classes takes as + input instance of this class or ``Null``. In case of ``Null`` instance of + ``declarations.decl_factory_t`` will be created. Using this class you can + easily extend functionality provided by built-in declarations. + +6. Sometimes, there is a need to find a declaration that match some criteria. + The was such functionality in pygccxml, but it was too limited. This + release fix the situation. pygccxml adds a set of classes that will help + you to deal with this problem. + +7. New cache - ``parser.directory_cache_t`` has been implemented. + ``parser.directory_cache_t`` uses individual files stored in a dedicated + cache directory to store the cached contents. + Thanks to Matthias Baas! + +8. ``parser.file_cache_t`` has been improved a lot. + Thanks to Allen Bierbaum! + +9. New file configuration is available: "cached source file". + ``parser.project_reader_t`` class will check for existence of GCC_XML + generated file. If it does not exist it will create one. If it do exist, + then the parser will use that file. + +10. Few helper functions has been added in order to make construction of + configuration file to be as easy as possible: + + * ``parser.create_text_fc`` - creates file configuration, that contains text + * ``parser.create_source_fc`` - creates file configuration, that contains + reference to regular source file + * ``parser.create_gccxml_fc`` - creates file configuration, that contains + reference to GCC_XML generated file + * ``parser.create_cached_source_fc`` - creates file configuration, that + contains reference to 2 files: GCC_XML generated file and regular source + file + +11. Small bug fixes. + +12. Documentation. Allen Bierbaum and Matthias Baas contributed so much in this + area. Almost every public function/class has now documentation string. + +13. Logging functionality has been added. pygccxml creates new logger + "pygccxml". Now it is possible to see what pygccxml is doing right now. + +14. I am sure I forgot something. + +Version 0.6.9 +------------- + +1. New functions: + + * *type_traits.is_void_pointer* + + * *type_traits.array_size* + + * *type_traits.array_item_type* + +2. Class *declarations.variable_t* has new property - *bit_fields* + +3. Now it is possible to specify "undefined" directives using + *parser.config_t* class. + +4. *patch* functionality has been introduced. GCC_XML generates wrong + default values for function arguments. *patch* functionality tries to fix + this. + +5. Small bug fixes + +Version 0.6.8 +------------- + +1. Small bug has been fixed. + +Version 0.6.7 +------------- + +1. New functions: + + * *type_traits.remove_pointer* + + * *type_traits.base_type* + + * *type_traits.is_convertible* + +2. A lot of small bug fixes. + +3. Few English mistakes have been fixed. + + .. attention:: + + There are 2 none backward compatible changes: + + * class with name **compaund_t** has been renamed to **compound_t** + + * word **pathes** has been replaced with **paths** + +4. There are new properties on + + * *declarations.declaration_t.top_parent* + + * *declarations.class_t.recursive_bases* returns all base classes of the + class + + * *declarations.class_t.recursive_derived* returns all derived classes of + the class + + * *member_calldef_t.access_type* + +5. New type has been introduced: *unknown_t*. There are use cases when + GCC_XML does not returns function return type. + +6. New implementation of *make_flatten* algorithm using generators. + By default old implementation will be used. + +7. *parser.file_configuration_t* interface has been changed. Now it is able + to keep: source file, text or GCC_XML generated file. If you are doing + something with code that is not changing you'd better use GCC_XML + generated file as content of the *parser.file_configuration_t*. Save your + time. + +8. There are some cases when GCC_XML reports *"restricted"*. In this case + pygccxml replaces *"restricted"* with *"volatile"*. diff --git a/docs/history.rst b/docs/history.rst index 3f20b20a..51f31b17 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -1,850 +1,12 @@ -Changes +History ======= -Introduction ------------- - The original author and maintainer for pygccxml was Roman Yakovenko (2004-2011). Holger Frydrych forked the project to work on python 3 support. Finally, Mark Moll forked the project a second time to carry on the work of porting the code to python 3 (keeping it compatible with python 2). -In Mai 2014, Michka Popoff and the Insight Software Consortium revived pygccxml -by setting up a git repositery on github, hosted along with gccxml. - -Version 1.7.3 -------------- - -1. Addition of an is_union() method in the type_traits module. - -2. type_traits.smart_pointer_traits will now classify std::shared_ptr as a - smart pointer (only boost::shared_ptr was recognized before) - -3. Fix a regression in undname_creator_t.format_argtypes - -4. C++xx flags are now correctly passed to CastXML. Allowed flags are: - "-std=c++98", "-std=c++03", "-std=c++11", "-std=c++14", "-std=c++1z" - Thanks to Mark Moll for the fix. - -5. Add better support for "typedef (class|struct) {} foo;" syntax when using - CastXML. GCCXML did not recognize the typedef. Fetching these - declarations can now be done with: .typedef("foo") or .class_("foo"). - -6. Add support for the future llvm 3.9. As in release v1.7.1, new structs and - typedefs are now exposed by llvm, which broke pyplusplus. - In this case these are ```__NSConstantString_tag``` and ```__NSConstantString```. - The two declarations are now hidden from the declarations tree, but can still - be generated by using the ``config.flags = ["f1"]`` option. - -7. Multiple fixes to adapt default arguments in functions for py++. Using the - latest version of CastXML is recommended. This makes sure default arguments - for function parameters are correctly defined, so that py++ can process them. - -8. Fix for exception when using castxml + gcc5 + std=c++11 and maps. - -9. Removed unittest2 dependency for testing with python 2.6 - -10. Testing: test with std::tr1 unordered containers for gcc >= 4.4.7 and castxml - -11. Cosmetic fix for generator name printed to stdout when launching unit tests - -12. Fix simple typo in example.py comment - -Thanks to the following people for their contribution to this release: -Mark Moll, Ashish Sadanandan, Mark Oates - -Version 1.7.2 -------------- - -1. Fix exception in is_copy_constructor when the constructor's argument was - a typedef. is_copy_constructor will now return False instead of failing. - See issue #27. - -2. Fix bug with utils.xml_generator being unset when reading cached file. - This could for example happen when reading a cached file from a second - python interpreter (e.g. in a subprocess or by calling pygccxml - multiple times from a script). See issue #27. - -3. SafeConfigParser is throwing a deprecation warning in python 3.2 and newer. - Use ConfigParser instead. Thanks to Mark Moll for the patch. - -4. Add support for cflags property in config files. - Thanks to Mark Moll for the patch. - -Version 1.7.1 -------------- - -1. Remove the __va_list_tag declaration from the tree when parsing with CastXML - - The __va_list_tag declarations are internal declarations, which are often - not needed. They are for example polluting the declarations tree when running - pyplusplus. - - This is optional but on by default. To still load the __va_list_tag declarations - in the tree, a config flag can be set like this: ``config.flags = ["f1"]``, - or by passing the ``flags=["f1"]`` argument the config setup. - -2. Some code cleanup - -3. Build new package for pypi. The ``1.7.0`` upload has gone wrong ... - - -Version 1.7.0 -------------- - -1. Added support for CastXML (https://github.com/CastXML/CastXML) - - GCCXML is deprecated and does no more work with modern compilers. - CastXML should be used instead. - - ``pygccxml 1.7.0`` is still compatible with GCCXML and no changes are needed for people working with GCCXML. - -2. [CastXML] A new function was introduced to help find which XML generator you are using. - - If the generator (GCCXML or CastXML) is in your path, it will be detected. - - .. code-block:: python - - generator_path, generator_name = pygccxml.utils.find_xml_generator() - -3. [CastXML] When using the configuration, you will need to tell pygccxml which xml generator you are using. - - .. code-block:: python - - xml_generator_config = parser.xml_generator_configuration_t( - xml_generator_path=generator_path, - xml_generator=generator_name, - ) - - ``gccxml_configuration_t`` is an alias of ``xml_generator_configuration_t``. - - ``load_gccxml_configuration`` is an alias of ``load_xml_generator_configuration``. - - Both can still be used but will be deprecated. - -4. [CastXML] The compiler path can be passed to castxml. - - This is done by using the ``compiler_path`` attribute in the configuration. - Note that this may be important because the resulting xml file is slightly different - depending on the compiler. - -5. [CastXML] Added support for some fields which have no location. - - These fields are: ``gp_offset``, ``fp_offset``, ``overflow_arg_area``, ``reg_save_area`` - -6. [CastXML] Mangled names are only available for functions and variables with CastXML. - - Getting the mangled attribute on a ``declaration`` will fail. - -7. [CastXML] Demangled names are not available. - - Getting a demangled name will fail. - -8. [CastXML] Add new container traits: - - ``unordered maps``, ``unordered sets``, ``multimaps``, ``multisets`` - -9. [CastXML] Annotations: - - Instead of using the ``__attribute((gccxml("string")))`` c++ syntax (see version 0.9.5), the ``__attribute__ ((annotate ("out")))`` can now be used to annotate code with CastXML. - -10. [CastXML] Disabled relinking of: - - .. code-block:: python - - rebind, void *> > - - This made the ``find_container_traits_tester`` unit tests fail with ``CastXML``. - This class defintion is present in the clang AST tree, but I don't know why it is - usefull. Please tell me if you need it so we can re-enable that featur in pygccxml. - -11. [Misc] Deprecated the ``compiler`` attribute and replaced it with a global ``utils.xml_generator`` variable. - - The ``compiler`` attribute was misleading; it was sometimes confused with the name and version of the xml generator. - - This change also fixes some internal problems with the algorithms cache. - -12. [Misc] ``declarations.has_trivial_copy`` was defintevely removed. - - Please use ``declarations.has_copy_constructor``. - - This was deprecated since version 0.9.5. - -13. [Misc] Remove ``gccxml`` logger from logger class (was deprecated). - - Please use ``cxx_parser`` instead. - -14. [Misc] Removed ``gccxml_runtime_error_t`` class. This was only used internally. - - Please use a normal ``RuntimeError`` instead. - -15. [Misc] Documentation was moved to readthedocs.org - - https://readthedocs.org/projects/pygccxml/ - -16. [Misc] Add quantifiedcode check - - https://www.quantifiedcode.com/app/project/117af14ef32a455fb7b3762e21083fb3 - -17. [Misc] Add option to keep xml files after errors, which is useful for debugging purposes. - -18. [Misc] Fix new pep8 warnings, clean up and simplify some code and comments - -19. [Misc] The compiler version debugging message is now hidden (closes #12) - -20. [Misc] Print less line separations in ``decl_printer``; this makes the output more compact. - -21. [Tests] Add new test for the ``contains_parent_dir`` function. - -22. [Tests] Add test for non copyable class with const class - -23. [Tests] Add test case for non copyable class due to const array - -24. [Doc] Small documentation update, moved people list to credits page, added new examples. - -25. [Misc] Add Travis unit tests for Python 3.5 - - -Version 1.6.2 -------------- - -1. Use setuptools instead of distutils for the packaging - -2. Change rights of declarations_cache.py and templates_tester.py - from -rwxr-xr-x+ to -rw-r--r--+, so that all the files have the same - execution rights. - -Version 1.6.1 -------------- - -1. Fix a regression introduced by previous changes. Syntax errors were introduced - in the part were you can check if a class is copyable or not (see #13). These - have been fixed now. - -Version 1.6 ------------ - -1. Moved the repository from mercurial to git - -2. Changed the documentation from epydoc to sphinx doc - -3. Setup the documentation as gh-page and add script to update the documentation - Just call "make gh-pages" on the root folder to create a commit with the - new documentation, which you may then push to the github repository. - The url for the documentation is now http://gccxml.github.io/pygccxml/ - -4. Add Travis unit tests for Python 2.6, 2.7, 3.2, 3.3 and 3.4 - The tests are run after each commit (see .travis.yml file in root folder) - https://travis-ci.org/gccxml/pygccxml - -5. Add automatic code coverage. The code coverage is run during each travis - run and the results are uploaded to https://coveralls.io/r/gccxml/pygccxml - -6. Fix copy_constructor unit test - -7. Deprecate parser.config_t (replaced by parser.gccxml_configuration_t) - -8. Fix for string comparison with future unicode literals - When using from __future__ import unicode_literals in python 2.7, - the call to the namespace() method would fail due to the isinstance/str - check. - - A is_str() function was added to the utils module, allowing for a - python 2 and python 3 compatible string check. - A unit test for this case was added. - -9. All the code is now pep8 compliant and is tested for this in an unit test - -10. Most of unused imports and variables were removed using the pyflakes tool - -11. Use new style python decorators (@property) everywhere - -12. Add new unit test for the example.py file - -13. Update the licence headers to reflect the change in maintainers - -Version 1.5.2 -------------- - -1. Make python 3.x compatible. Still works with python 2.6 and python 2.7. - -2. Add .dylib parser for Darwin - -3. Fix some unit tests - -4. workaround for problem with boost >=1.54 - -5. Simpler way of checksumming files in a python 2 and 3 compatible way - -6. Prevent warnings to be treated as fatal errors in py++ - -7. "has_inline" property was added to ``declarations.calldef_t`` class. - -8. Thanks to Aron Xu, for pointing out that it is better to use "os.name", - instead of "sys.platform" for platform specific logic. - -9. "__int128_t" and "__uint128_t" types were introduced. Many thanks to Gustavo Carneiro - for providing the patch. - -Version 1.5.1 -------------- - -1. adding problematic use case, contributed by Zbigniew Mandziejewicz - -2. Adding "explicit" attribute to constructor_t class - -3. "List symbols" (`nm`) utility invocation was improved and now handles - right relative paths and paths with spaces. Many thanks to Alejandro Dubrovsky - for providing the patch. - -4. Fix for "get dependencies" functionality - -5. Allow the process to continue, even in case the binary parser can not find the relevant declaration - -6. Fix bug related to merging free functions - -7. Improve decl_printer - sort declarations before printing - -8. Added new tests and ported tests to x86_64 architecture - -Version 1.5.0 -------------- - -1. Fix small bug in matcher - don't match namespaces by their location - -2. Documentation update and cleanup. (using sphinx-doc now). - -3. Fixing small bug on Windows, related to parsing configuration file - -4. Update setup.py - -5. fix 2779781 bug( pygccxml reverses array dimensions ) - -Note about version numbers before 1.5.0 ---------------------------------------- - -When the project moved from svn to git, versions were tagged from 1.0.0 on. -Note that there was no 1.2, 1.3 nor 1.4 version (this is maybe due to the -many forks and the slow down of the maintenance effort). - -Version 1.1.0 -------------- - -1. bsc and mspdb packages were deprecated - -2. Adding new functionality and improving initial environment handling - -3. Adding ability to dump exported classes - -4. Added more tests - -5. Add handling for "C" functions - -6. Fix bug "pygccxml parses const volatile variable args as just const" - -7. Rename bparser to binary_parsers - -8. Adding .so file parser - -9. Replace md5 with hashlib module (removes deprecation warnings) - -Version 1.0 ------------ - -1. Support for ellipsis was added. - - Warning: this feature introduce backward compatibility problem! - - Description: - - .. code-block:: c++ - - void do_smth( int, ... ) - - Before this change, pygccxml would report that the function ``do_smth`` has - only one argument. - - After this change, pygccxml will report that the function has two arguments. - The second argument type will be ``declarations.ellipsis_t``. All classes, - which describe callables, have new property ``has_ellipsis``. It the value of - the property is ``True``, than the function has ellipsis in its definition. - -2. New experimental back-end, based on ``.pdb`` (progam database file), was added. - -3. New high-level API wrapper for ``.bsc`` (browse source code file) was added. - -4. The recomended GCC_XML version to use with this release is CVS revision 123. - This revision introduces small, but very important feature. GCC_XML - started to dump artificial declarations (constructor, destructor, operator=). - ``pygccxml.declarations.type_traits`` functions were updated to use the new - information. - -5. ``declarations.decl_printer_t`` class dumps almost all available information - about a declaration. - -6. ``declarations.is_same_function`` was fixed and now it treats - "covariant returns" right. - -7. Search algorithm was improved for template instantiated classes. From - now, a spaces within the class name doesn't matter. - -8. pygccxml unit tests functionality was improved. Many thanks to Gustavo Carneiro. - -Version 0.9.5 -------------- - -1. Class ``free_operator_t`` is now able to provide references to the class declarations - instances it works on. - -2. Support for `GCC-XML attributes`_ was added. Many thanks to Miguel Lobo for - the implementation. - -.. _`GCC-XML attributes`: http://www.gccxml.org/HTML/Running.html - -3. A bug in parsing a function exception specification was fixed. Many thanks to - Jeremy Sanders. - -4. Support for a type/class "align", "offset" and "size" was added. Many thanks to - Ben Schleimer for the implementation. - -5. Support for GCC-XML 0.9 was added. - -6. Support for ``__restrict__`` was added. - -7. ``declarations.has_trivial_copy`` was renamed to ``declarations.has_copy_constructor``. - The old name is still available, but will be removed soon. - -8. ``declarations.priority_queue`` was renamed to ``declarations.priority_queue_traits``. -9. ``declarations.find_container_traits`` function was added. - -10. Support for "partial name" was added. "Partial name" is the class name, without - template default arguments. The functionality was added to std containers - classes. - -11. ``declarations.class_t`` and ``declarations.class_declaration_t`` has new property - - ``container_traits``. This property describes std container element class. - -12. All logging is now done to ``stderr`` instead of ``stdout``. - -Version 0.9.0 -------------- - -1. Performance was improved. pygccxml is now 30-50% faster. The improvement - was achieved by using `cElementTree`_ package, ``iterparse`` functionality, - instead of standard XML SAX API. If `cElementTree`_ package is not available, - the built-in XML SAX package is used. - -.. _`cElementTree` : http://effbot.org/zone/celementtree.htm - -2. ``is_base_and_derived`` function was changed. The second argument could be - a tuple, which contains classes. The function returns ``True`` if at least one - class derives from the base one. - -.. line separator - -3. Class ``calldef_t`` has property - ``does_throw``. It describes - whether the function throws any exception or not. - -.. line separator - -4. Bug fixes: small bug was fixed in functionality that corrects GCC-XML reported - function default arguments. Reference to "enum" declaration extracted properly. - Many thanks to Martin Preisler for reporting the bug. - -.. line separator - -5. New type traits have been added: - - - * ``is_std_ostream`` - * ``is_std_wostream`` - -.. line separator - -6. C++ does not define implicit conversion between an integral type and ``void*``. - ``declarations.is_convertible`` type traits was fixed. - -.. line separator - -7. ``declarations.is_noncopyable`` type traits implementation was slightly changed. - Now it checks explicitly that class has: - - * default constructor - * copy constructor - * ``operator=`` - * destructor - - If all listed functions exist, than the algorithm returns ``False``, otherwise - it will continue to execute previous logic. - -.. line separator - -8. ``declarations.class_declaration_t`` has new property - ``aliases``. This is - a list of all aliases to the class declaration. - -.. line separator - -9. The message of the exception, which is raised from ``declarations.mdecl_wrapper_t`` - class was improved and now clearly explains what the problem is. - -.. line separator - -Version 0.8.5 -------------- - -1. Added new functionality: "I depend on them". Every declaration can report - types and declarations it depends on. - -2. ``signed char`` and ``char`` are two different types. This bug was fixed and - now pygccxml treats them right. Many thanks to Gaetan Lehmann for reporting - the bug. - -3. Declarations, read from GCC-XML generated file, could be saved in cache. - -4. New type traits have been added: - - * ``is_bool`` - -5. Small improvement to algorithm, which extracts ``value_type`` - ( ``mapped_type`` ) from "std" containers. - -6. Few aliases to long method name were introduced: - - ================================= ========================== - Name Alias - ================================= ========================== - ``scopedef_t.variable`` ``scopedef_t.var`` - ``scopedef_t.variables`` ``scopedef_t.vars`` - ``scopedef_t.member_function`` ``scopedef_t.mem_fun`` - ``scopedef_t.member_functions`` ``scopedef_t.mem_funs`` - ``scopedef_t.free_function`` ``scopedef_t.free_fun`` - ``scopedef_t.free_functions`` ``scopedef_t.free_funs`` - ================================= ========================== - -7. Fixing bug related to array size and cache. - -Version 0.8.2 -------------- - -1. Few small bug fix and unit tests have been introduced on 64 Bit platforms. - Many thanks to Gottfried Ganssauge! He also help me to discover and fix - some important bug in ``type_traits.__remove_alias`` function, by introducing - small example that reproduced the error. - -2. Huge speed improvement has been achieved (x10). Allen Bierbaum suggested to - save and reuse results of different pygccxml algorithms: - - * ``declarations.remove_alias`` - * ``declarations.full_name`` - * ``declarations.access_type`` - * ``declarations.demangled_name`` - * ``declarations.declaration_path`` - -3. Interface changes: - - * ``declarations.class_t``: - - + ``set_members`` method was removed - - + ``adopt_declaration`` method was introduced, instead of ``set_members`` - - * ``declarations.array_t`` class "set" accessor for size property was added. - - * ``declarations.namespace_t.adopt_declaration`` method was added. - - * ``declarations.variable_t.access_type`` property was added. - -4. New type traits have been added: - - * ``is_same_function`` - -5. Few bug were fixed. - -6. Documentation was improved. - -Version 0.8.1 -------------- - -1. pygccxml has been ported to MacOS X. Many thanks to Darren Garnier! - -2. New type traits have been added: - - * ``enum_traits`` - - * ``class_traits`` - - * ``class_declaration_traits`` - - * ``is_std_string`` - - * ``is_std_wstring`` - - * ``remove_declarated`` - - * ``has_public_less`` - - * ``has_public_equal`` - - * ``has_public_binary_operator`` - - * ``smart_pointer_traits`` - - * ``list_traits`` - - * ``deque_traits`` - - * ``queue_traits`` - - * ``priority_queue`` - - * ``vector_traits`` - - * ``stack_traits`` - - * ``map_traits`` - - * ``multimap_traits`` - - * ``hash_map_traits`` - - * ``hash_multimap_traits`` - - * ``set_traits`` - - * ``hash_set_traits`` - - * ``multiset_traits`` - - * ``hash_multiset_traits`` - -3. ``enumeration_t`` class interface was changed. Enumeration values are kept - in a list, instead of a dictionary. ``get_name2value_dict`` will build for - you dictionary, where key is an enumeration name, and value is an enumeration - value. - - This has been done in order to provide stable order of enumeration values. - -4. Now you can pass operator symbol, as a name to query functions: - - .. code-block:: python - - cls = global_namespace.class_( 'my_class' ) - op = cls.operator( '<' ) - #instead of - op = cls.operator( symbol='<' ) - -5. pygccxml improved a lot functionality related to providing feedback to user: - - * every package has its own logger - - * only important user messages are written to ``stdout`` - - * user messages are clear - -6. Support to Java native types has been added. - -7. It is possible to pass an arbitrary string as a parameter to GCC_XML. - -8. Native java types has been added to fundamental types. - -9. Cache classes implementation was improved. - -10. Few bug were fixed. - -11. Documentation was improved. - -12. ``mdecl_wrapper_t.decls`` property was renamed to ``declarations``. - The reason is that the current name ( ``decls`` ) conflicts with the method - of the same name in the decl interface from ``declarations.scopedef_t`` class. - - So for example: - - .. code-block:: python - - classes = ns.decls("class") - classes.decls("method") - - This will fail because it finds the attribute decls which is not a callable. - -Version 0.8 ------------ - -1. pygccxml now has power "select" interface. Read more about this cool feature - in tutorials. - -2. Improved support for template instantiations. pygccxml now take into - account demangled name of declarations. Please refer to documentation for - more explanantion. - -3. ``dummy_type_t`` - new type in types hierarchy. This is a very useful class - for code generation projects. - -4. New function - ``get_global_namespace``. As you can guess, it will find and - return reference to global namespace. - -5. New functionality in ``type_traits`` - ``has_public_assign``. This function - will return True, if class has public assign operator. - -6. ``declarations.class_t`` has new property - ``aliases``. This is a list of - all class aliases. - -7. Bug fixes. - -8. Documentation has been updated/written/improved. - -Version 0.7.1 -------------- - -**Attention - this going to be last version that is tested with Python 2.3** - -1. New fundamental types has been added - - * complex float - - * complex double - - * complex long double - -2. **Attention - non backward compatible change** - - ``declarations.filtering.user_defined`` and ``declarations.filtering.by_location`` - implementation has been changed. In previous version of those functions, - ``decls`` list has been changed in place. This was wrong behavior. Now, - those functions will return new list, which contains all desired declarations. - -3. Few new type traits has been added - - * *type_traits.has_destructor* - - * *type_traits.has_public_destructor* - - * *type_traits.has_public_constructor* - - * *type_traits.is_noncopyable* - -4. ``decl_printer_t`` class and ``print_declarations`` function have been added. - Now you can print in a nice way your declaration tree or part of it. - Thanks to Allen Bierbaum! - -5. New class ``declarations.decl_factory_t`` has been added. This is a default - factory for all declarations. From now all relevant parser classes takes as - input instance of this class or ``Null``. In case of ``Null`` instance of - ``declarations.decl_factory_t`` will be created. Using this class you can - easily extend functionality provided by built-in declarations. - -6. Sometimes, there is a need to find a declaration that match some criteria. - The was such functionality in pygccxml, but it was too limited. This - release fix the situation. pygccxml adds a set of classes that will help - you to deal with this problem. - -7. New cache - ``parser.directory_cache_t`` has been implemented. - ``parser.directory_cache_t`` uses individual files stored in a dedicated - cache directory to store the cached contents. - Thanks to Matthias Baas! - -8. ``parser.file_cache_t`` has been improved a lot. - Thanks to Allen Bierbaum! - -9. New file configuration is available: "cached source file". - ``parser.project_reader_t`` class will check for existence of GCC_XML - generated file. If it does not exist it will create one. If it do exist, - then the parser will use that file. - -10. Few helper functions has been added in order to make construction of - configuration file to be as easy as possible: - - * ``parser.create_text_fc`` - creates file configuration, that contains text - * ``parser.create_source_fc`` - creates file configuration, that contains - reference to regular source file - * ``parser.create_gccxml_fc`` - creates file configuration, that contains - reference to GCC_XML generated file - * ``parser.create_cached_source_fc`` - creates file configuration, that - contains reference to 2 files: GCC_XML generated file and regular source - file - -11. Small bug fixes. - -12. Documentation. Allen Bierbaum and Matthias Baas contributed so much in this - area. Almost every public function/class has now documentation string. - -13. Logging functionality has been added. pygccxml creates new logger - "pygccxml". Now it is possible to see what pygccxml is doing right now. - -14. I am sure I forgot something. - -Version 0.6.9 -------------- - -1. New functions: - - * *type_traits.is_void_pointer* - - * *type_traits.array_size* - - * *type_traits.array_item_type* - -2. Class *declarations.variable_t* has new property - *bit_fields* - -3. Now it is possible to specify "undefined" directives using - *parser.config_t* class. - -4. *patch* functionality has been introduced. GCC_XML generates wrong - default values for function arguments. *patch* functionality tries to fix - this. - -5. Small bug fixes - -Version 0.6.8 -------------- - -1. Small bug has been fixed. - -Version 0.6.7 -------------- - -1. New functions: - - * *type_traits.remove_pointer* - - * *type_traits.base_type* - - * *type_traits.is_convertible* - -2. A lot of small bug fixes. - -3. Few English mistakes have been fixed. - - .. attention:: - - There are 2 none backward compatible changes: - - * class with name **compaund_t** has been renamed to **compound_t** - - * word **pathes** has been replaced with **paths** - -4. There are new properties on - - * *declarations.declaration_t.top_parent* - - * *declarations.class_t.recursive_bases* returns all base classes of the - class - - * *declarations.class_t.recursive_derived* returns all derived classes of - the class - - * *member_calldef_t.access_type* - -5. New type has been introduced: *unknown_t*. There are use cases when - GCC_XML does not returns function return type. - -6. New implementation of *make_flatten* algorithm using generators. - By default old implementation will be used. - -7. *parser.file_configuration_t* interface has been changed. Now it is able - to keep: source file, text or GCC_XML generated file. If you are doing - something with code that is not changing you'd better use GCC_XML - generated file as content of the *parser.file_configuration_t*. Save your - time. +In Mai 2014, Michka Popoff and the Insight Software Consortium revived pygccxml +by setting up a git repositery on Github, hosted along with gccxml. -8. There are some cases when GCC_XML reports *"restricted"*. In this case - pygccxml replaces *"restricted"* with *"volatile"*. +The full changelog of this project can be found in CHANGELOG.md file. From 92eb69ca96cfcaf5b33d437dc0b57a9327bc5193 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 6 Apr 2016 00:05:52 +0200 Subject: [PATCH 100/268] Regroup the history and the credits on a single page --- docs/credits.rst | 28 ---------------------------- docs/history.rst | 48 +++++++++++++++++++++++++++++++++++++++++++++--- docs/index.rst | 1 - 3 files changed, 45 insertions(+), 32 deletions(-) delete mode 100644 docs/credits.rst diff --git a/docs/credits.rst b/docs/credits.rst deleted file mode 100644 index f40be06f..00000000 --- a/docs/credits.rst +++ /dev/null @@ -1,28 +0,0 @@ -Contributors ------------- - -Thanks to all the people that have contributed patches, bug reports and suggestions, -or supported this project: - -* Roman Yakovenko (original author) -* Roman Yakovenko's wife - Yulia -* Michka Popoff -* Brad King -* Matt Mccormick -* Mark Moll -* Holger Frydrych -* John Pallister -* Matthias Baas -* Allen Bierbaum -* Georgiy Dernovoy -* Darren Garnier -* Gottfried Ganssauge -* Gaetan Lehmann -* Martin Preisler -* Miguel Lobo -* Jeremy Sanders -* Ben Schleimer -* Gustavo Carneiro -* Christopher Bruns -* Alejandro Dubrovsky -* Aron Xu diff --git a/docs/history.rst b/docs/history.rst index 51f31b17..97097786 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -1,12 +1,54 @@ +History and Credits +=================== + History -======= +------- The original author and maintainer for pygccxml was Roman Yakovenko (2004-2011). + Holger Frydrych forked the project to work on python 3 support. Finally, Mark Moll forked the project a second time to carry on the work of porting the code to python 3 (keeping it compatible with python 2). In Mai 2014, Michka Popoff and the Insight Software Consortium revived pygccxml -by setting up a git repositery on Github, hosted along with gccxml. +by setting up a git repositery on GitHub, hosted along with gccxml. + +The full changelog can be found in the CHANGELOG.md file. + +Contributors +------------ + +Thanks to all the people that have contributed patches, bug reports and suggestions, +or supported this project. + +* Roman Yakovenko (original author) +* Michka Popoff (actual maintainer) + +A special thanks to the Insight Software Consortium for their help and collaboration, +especially: + +* Brad King +* Matt Mccormick + +Contributors can be found on github's contributors page: https://github.com/gccxml/pygccxml/graphs/contributors + +Here is the original list of contributors from before the GitHub migration. -The full changelog of this project can be found in CHANGELOG.md file. +* Roman Yakovenko's wife - Yulia +* Mark Moll +* Holger Frydrych +* John Pallister +* Matthias Baas +* Allen Bierbaum +* Georgiy Dernovoy +* Darren Garnier +* Gottfried Ganssauge +* Gaetan Lehmann +* Martin Preisler +* Miguel Lobo +* Jeremy Sanders +* Ben Schleimer +* Gustavo Carneiro +* Christopher Bruns +* Alejandro Dubrovsky +* Aron Xu diff --git a/docs/index.rst b/docs/index.rst index 432da9b9..986c7e50 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -59,7 +59,6 @@ Documentation contents links releasing history - credits apidocs/api .. _`Boost Software License`: http://boost.org/more/license_info.html From 17df92e99ade2946aeaafc381300ac58a92a7f4f Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 7 Apr 2016 23:21:19 +0200 Subject: [PATCH 101/268] Update changelog --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89f9c817..981c7713 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,19 @@ Changes ======= +Version 1.8.0 (not yet released) +-------------------------------- + +* find_xml_generator will now look for castxml first + +* Deprecate the ns() method. The namespace() method can be used instead. + +* General code style overhaul (with the help of quantifiedcode.com) + +* Added a bunch of new examples + +* Documentation update and cleanup + Version 1.7.3 ------------- From 0e3f12810f4d285bf8d4bf7e8b05ad597114a908 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 14 Apr 2016 23:25:20 +0200 Subject: [PATCH 102/268] Make CastXML the default in the config --- pygccxml/parser/config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index 610b1f38..179f189f 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -41,7 +41,7 @@ def __init__( undefine_symbols=None, cflags="", compiler=None, - xml_generator="gccxml", + xml_generator="castxml", keep_xml=False, compiler_path=None, flags=None): @@ -207,7 +207,7 @@ def __init__( ignore_gccxml_output=False, cflags="", compiler=None, - xml_generator="gccxml", + xml_generator="castxml", keep_xml=False, compiler_path=None, flags=None): From 55fffea002c7d6b7e669a5c2522630b023a522fd Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 14 Apr 2016 23:36:01 +0200 Subject: [PATCH 103/268] Use with context manager when opening files --- pygccxml/binary_parsers/parsers.py | 20 ++++++++++---------- pygccxml/parser/source_reader.py | 5 ++--- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/pygccxml/binary_parsers/parsers.py b/pygccxml/binary_parsers/parsers.py index 4ea79e1a..024d8e5a 100644 --- a/pygccxml/binary_parsers/parsers.py +++ b/pygccxml/binary_parsers/parsers.py @@ -146,16 +146,16 @@ def __init__(self, global_ns, map_file_path): def load_symbols(self): """returns dictionary { decorated symbol : original declaration name }""" - f = open(self.binary_file) - lines = [] - was_exports = False - for line in f: - if was_exports: - lines.append(line) - elif 'Exports' == line.strip(): - was_exports = True - else: - pass + with open(self.binary_file) as f: + lines = [] + was_exports = False + for line in f: + if was_exports: + lines.append(line) + elif 'Exports' == line.strip(): + was_exports = True + else: + pass index = 0 result = [] diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 65924bca..b4f30401 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -351,9 +351,8 @@ def create_xml_file_from_string(self, content, destination=None): header_file = pygccxml.utils.create_temp_file_name(suffix='.h') try: - header_file_obj = open(header_file, 'w+') - header_file_obj.write(content) - header_file_obj.close() + with open(header_file, "w+") as header: + header.write(content) xml_file = self.create_xml_file(header_file, destination) finally: pygccxml.utils.remove_file_no_raise(header_file, self.__config) From ea5efe54df60375215b746020251b7798ae460ff Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 14 Apr 2016 23:10:54 +0200 Subject: [PATCH 104/268] Do not overload built-in function (type) For this, the type getters/setters are deprecated, so people have time to adapt their code. .type is to be replaced by .decl_type --- pygccxml/declarations/class_declaration.py | 2 +- pygccxml/declarations/container_traits.py | 2 +- pygccxml/declarations/decl_printer.py | 8 ++--- pygccxml/declarations/matchers.py | 4 +-- pygccxml/declarations/type_traits.py | 8 ++--- pygccxml/declarations/typedef.py | 26 +++++++++++--- pygccxml/declarations/variable.py | 26 +++++++++++--- pygccxml/parser/linker.py | 4 +-- pygccxml/parser/project_reader.py | 2 +- pygccxml/parser/source_reader.py | 2 +- unittests/array_bug_tester.py | 8 ++--- unittests/core_tester.py | 40 +++++++++++----------- unittests/declarations_tester.py | 2 +- unittests/string_traits_tester.py | 4 +-- unittests/type_traits_tester.py | 4 +-- unittests/unnamed_classes_tester.py | 6 ++-- 16 files changed, 90 insertions(+), 58 deletions(-) diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 822d374f..1476b4d7 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -597,7 +597,7 @@ def find_noncopyable_vars(self): for mvar in mvars: - type_ = tt.remove_reference(mvar.type) + type_ = tt.remove_reference(mvar.decl_type) if tt.is_const(type_): no_const = tt.remove_const(type_) diff --git a/pygccxml/declarations/container_traits.py b/pygccxml/declarations/container_traits.py index 545c1469..99d6a130 100644 --- a/pygccxml/declarations/container_traits.py +++ b/pygccxml/declarations/container_traits.py @@ -476,7 +476,7 @@ def __find_xxx_type( if not result: if isinstance(cls_declaration, class_declaration.class_t): xxx_type = cls_declaration.typedef( - xxx_typedef, recursive=False).type + xxx_typedef, recursive=False).decl_type result = type_traits.remove_declarated(xxx_type) else: xxx_type_str = templates.args(cls_declaration.name)[xxx_index] diff --git a/pygccxml/declarations/decl_printer.py b/pygccxml/declarations/decl_printer.py index 07dd18d9..b93ef154 100644 --- a/pygccxml/declarations/decl_printer.py +++ b/pygccxml/declarations/decl_printer.py @@ -414,7 +414,7 @@ def visit_typedef(self): curr_level * self.INDENT_SIZE + 'alias to: ' + - self.__inst.type.decl_string + + self.__inst.decl_type.decl_string + os.linesep) def visit_variable(self): @@ -425,7 +425,7 @@ def visit_variable(self): curr_level * self.INDENT_SIZE + 'type: %s' % - self.__inst.type.decl_string) + self.__inst.decl_type.decl_string) self.writer( ' ' * curr_level * @@ -442,7 +442,7 @@ def visit_variable(self): bits.ljust( self.JUSTIFY)) - byte_size = 'size: %d' % self.__inst.type.byte_size + byte_size = 'size: %d' % self.__inst.decl_type.byte_size self.writer( ' ' * curr_level * @@ -450,7 +450,7 @@ def visit_variable(self): byte_size.ljust( self.JUSTIFY)) try: - byte_align = 'align: %d' % self.__inst.type.byte_align + byte_align = 'align: %d' % self.__inst.decl_type.byte_align self.writer( ' ' * curr_level * diff --git a/pygccxml/declarations/matchers.py b/pygccxml/declarations/matchers.py index b98c5cbf..cc95868e 100644 --- a/pygccxml/declarations/matchers.py +++ b/pygccxml/declarations/matchers.py @@ -324,10 +324,10 @@ def __call__(self, decl): return False if self.type is not None: if isinstance(self.type, cpptypes.type_t): - if self.type != decl.type: + if self.type != decl.decl_type: return False else: - if self.type != decl.type.decl_string: + if self.type != decl.decl_type.decl_string: return False return True diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 21fbd0e8..83870825 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -38,7 +38,7 @@ def __remove_alias(type_): return __remove_alias(type_.type) if isinstance(type_, cpptypes.declarated_t) and \ isinstance(type_.declaration, typedef.typedef_t): - return __remove_alias(type_.declaration.type) + return __remove_alias(type_.declaration.decl_type) if isinstance(type_, cpptypes.compound_t): type_.base = __remove_alias(type_.base) return type_ @@ -51,7 +51,7 @@ def remove_alias(type_): if isinstance(type_, cpptypes.type_t): type_ref = type_ elif isinstance(type_, typedef.typedef_t): - type_ref = type_.type + type_ref = type_.decl_type else: pass # not a valid input, just return it if not type_ref: @@ -80,10 +80,10 @@ def decompose_type(tp): if isinstance(tp, cpptypes.compound_t): return [tp] + decompose_type(tp.base) elif isinstance(tp, typedef.typedef_t): - return decompose_type(tp.type) + return decompose_type(tp.decl_type) elif isinstance(tp, cpptypes.declarated_t) and \ isinstance(tp.declaration, typedef.typedef_t): - return decompose_type(tp.declaration.type) + return decompose_type(tp.declaration.decl_type) else: return [tp] diff --git a/pygccxml/declarations/typedef.py b/pygccxml/declarations/typedef.py index 5ea7bf21..071cd4ad 100644 --- a/pygccxml/declarations/typedef.py +++ b/pygccxml/declarations/typedef.py @@ -7,6 +7,7 @@ defines class that describes C++ typedef declaration """ +import warnings from . import declaration from . import dependencies @@ -22,12 +23,12 @@ def __init__(self, name='', type=None): def _get__cmp__items(self): """implementation details""" - return [self.type] + return [self.decl_type] def __eq__(self, other): if not declaration.declaration_t.__eq__(self, other): return False - return self.type == other.type + return self.decl_type == other.decl_type def __hash__(self): return super.__hash__(self) @@ -35,14 +36,29 @@ def __hash__(self): @property def type(self): """reference to the original :class:`type `""" + warnings.warn( + "typedef_t.type is deprecated.\n" + + "Please use typedef_t.decl_type instead.", DeprecationWarning) return self._type @type.setter - def type(self, type): - self._type = type + def type(self, _type): + warnings.warn( + "typedef_t.type is deprecated.\n" + + "Please use typedef_t.decl_type instead.", DeprecationWarning) + self._type = _type + + @property + def decl_type(self): + """reference to the original :class:`decl_type `""" + return self._type + + @decl_type.setter + def decl_type(self, decl_type): + self._type = decl_type def i_depend_on_them(self, recursive=True): - return [dependencies.dependency_info_t(self, self.type)] + return [dependencies.dependency_info_t(self, self.decl_type)] @property def byte_size(self): diff --git a/pygccxml/declarations/variable.py b/pygccxml/declarations/variable.py index 4f42e418..0d62d6d5 100644 --- a/pygccxml/declarations/variable.py +++ b/pygccxml/declarations/variable.py @@ -7,6 +7,7 @@ defines class that describes C++ global and member variable declaration """ +import warnings from . import declaration from . import dependencies from . import class_declaration @@ -35,13 +36,13 @@ def __init__( def _get__cmp__items(self): """implementation details""" - return [self.type, self.type_qualifiers, self.value] + return [self.decl_type, self.type_qualifiers, self.value] def __eq__(self, other): """implementation details""" if not declaration.declaration_t.__eq__(self, other): return False - return self.type == other.type \ + return self.decl_type == other.decl_type \ and self.type_qualifiers == other.type_qualifiers \ and self.value == other.value \ and self.bits == other.bits @@ -52,11 +53,26 @@ def __hash__(self): @property def type(self): """reference to the variable :class:`type `""" + warnings.warn( + "variable_t.type is deprecated.\n" + + "Please use variable_t.decl_type instead.", DeprecationWarning) return self._type @type.setter - def type(self, type): - self._type = type + def type(self, _type): + warnings.warn( + "variable_t.type is deprecated.\n" + + "Please use variable_t.decl_type instead.", DeprecationWarning) + self._type = _type + + @property + def decl_type(self): + """reference to the variable :class:`decl_type `""" + return self._type + + @decl_type.setter + def decl_type(self, decl_type): + self._type = decl_type @property def type_qualifiers(self): @@ -120,7 +136,7 @@ def mangled(self, mangled): self._mangled = mangled def i_depend_on_them(self, recursive=True): - return [dependencies.dependency_info_t(self, self.type)] + return [dependencies.dependency_info_t(self, self.decl_type)] def get_mangled_name(self): if not self._mangled and not self._demangled \ diff --git a/pygccxml/parser/linker.py b/pygccxml/parser/linker.py index baf9e4d8..6127522f 100644 --- a/pygccxml/parser/linker.py +++ b/pygccxml/parser/linker.py @@ -158,10 +158,10 @@ def visit_namespace(self): self.__link_members() def visit_typedef(self): - self.__inst.type = self.__link_type(self.__inst.type) + self.__inst.decl_type = self.__link_type(self.__inst.decl_type) def visit_variable(self): - self.__inst.type = self.__link_type(self.__inst.type) + self.__inst.decl_type = self.__link_type(self.__inst.decl_type) def visit_void(self): pass diff --git a/pygccxml/parser/project_reader.py b/pygccxml/parser/project_reader.py index a7542cef..30c1cddc 100644 --- a/pygccxml/parser/project_reader.py +++ b/pygccxml/parser/project_reader.py @@ -582,5 +582,5 @@ def get_from_type(cpptype): decl, (pygccxml.declarations.typedef_t, pygccxml.declarations.variable_t)): - types.extend(get_from_type(decl.type)) + types.extend(get_from_type(decl.decl_type)) return types diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index b4f30401..4c9f638e 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -36,7 +36,7 @@ def bind_aliases(decls): typedefs = [ decl for decl in decls if isinstance(decl, declarations.typedef_t)] for decl in typedefs: - type_ = declarations.remove_alias(decl.type) + type_ = declarations.remove_alias(decl.decl_type) if not isinstance(type_, declarations.declarated_t): continue cls_inst = type_.declaration diff --git a/unittests/array_bug_tester.py b/unittests/array_bug_tester.py index e943c4b3..8f4f31da 100644 --- a/unittests/array_bug_tester.py +++ b/unittests/array_bug_tester.py @@ -20,7 +20,7 @@ def test1(self): src_reader = parser.source_reader_t(self.config) global_ns = declarations.get_global_namespace( src_reader.read_string(code)) - aaaa_type = global_ns.variable('aaaa').type + aaaa_type = global_ns.variable('aaaa').decl_type self.assertTrue( 'int[2][3][4][5]' == aaaa_type.decl_string, aaaa_type.decl_string) @@ -30,7 +30,7 @@ def test2(self): src_reader = parser.source_reader_t(self.config) global_ns = declarations.get_global_namespace( src_reader.read_string(code)) - aaaa_type = global_ns.variable('aaaa').type + aaaa_type = global_ns.variable('aaaa').decl_type self.assertTrue( 'int *[2][3][4][5]' == aaaa_type.decl_string, aaaa_type.decl_string) @@ -40,7 +40,7 @@ def test3(self): src_reader = parser.source_reader_t(self.config) global_ns = declarations.get_global_namespace( src_reader.read_string(code)) - aaaa_type = global_ns.variable('aaaa').type + aaaa_type = global_ns.variable('aaaa').decl_type self.assertTrue( 'int[2]' == aaaa_type.decl_string, aaaa_type.decl_string) @@ -50,7 +50,7 @@ def test4(self): src_reader = parser.source_reader_t(self.config) global_ns = declarations.get_global_namespace( src_reader.read_string(code)) - aaaa_type = global_ns.variable('aaaa').type + aaaa_type = global_ns.variable('aaaa').decl_type self.assertTrue( '::xyz[2][3]' == aaaa_type.decl_string, aaaa_type.decl_string) diff --git a/unittests/core_tester.py b/unittests/core_tester.py index 7f1b7973..723dc2e2 100644 --- a/unittests/core_tester.py +++ b/unittests/core_tester.py @@ -336,7 +336,7 @@ def test_fundamental_types(self): typedef, "unable to find typedef to build-in type '%s'" % fundamental_type_name) - if typedef.type.decl_string != fundamental_type.decl_string: + if typedef.decl_type.decl_string != fundamental_type.decl_string: errors.append( "there is a difference between typedef base type " + "name('%s') and expected one('%s')" % @@ -348,7 +348,7 @@ def test_compound_types(self): decl_type=declarations.typedef_t, name='typedef_const_int') self._test_type_composition( - typedef_inst.type, + typedef_inst.decl_type, declarations.const_t, declarations.int_t) @@ -356,7 +356,7 @@ def test_compound_types(self): decl_type=declarations.typedef_t, name='typedef_pointer_int') self._test_type_composition( - typedef_inst.type, + typedef_inst.decl_type, declarations.pointer_t, declarations.int_t) @@ -364,7 +364,7 @@ def test_compound_types(self): decl_type=declarations.typedef_t, name='typedef_reference_int') self._test_type_composition( - typedef_inst.type, + typedef_inst.decl_type, declarations.reference_t, declarations.int_t) @@ -372,15 +372,15 @@ def test_compound_types(self): decl_type=declarations.typedef_t, name='typedef_const_unsigned_int_const_pointer') self._test_type_composition( - typedef_inst.type, + typedef_inst.decl_type, declarations.const_t, declarations.pointer_t) self._test_type_composition( - typedef_inst.type.base, + typedef_inst.decl_type.base, declarations.pointer_t, declarations.const_t) self._test_type_composition( - typedef_inst.type.base.base, + typedef_inst.decl_type.base.base, declarations.const_t, declarations.unsigned_int_t) @@ -388,13 +388,13 @@ def test_compound_types(self): decl_type=declarations.typedef_t, name='typedef_volatile_int') self._test_type_composition( - typedef_inst.type, + typedef_inst.decl_type, declarations.volatile_t, declarations.int_t) var_inst = self.global_ns.variable('array255') self._test_type_composition( - var_inst.type, + var_inst.decl_type, declarations.array_t, declarations.int_t) @@ -403,15 +403,15 @@ def test_compound_types(self): name='typedef_EFavoriteDrinks') self.assertTrue( isinstance( - typedef_inst.type, + typedef_inst.decl_type, declarations.declarated_t), " typedef to enum should be 'declarated_t' instead of '%s'" % - typedef_inst.type.__class__.__name__) + typedef_inst.decl_type.__class__.__name__) enum_declaration = self.global_ns.enum('EFavoriteDrinks') self.assertTrue( - typedef_inst.type.declaration is enum_declaration, + typedef_inst.decl_type.declaration is enum_declaration, "instance of declaration_t has reference to '%s' instead of '%s'" % - (typedef_inst.type.declaration.name, + (typedef_inst.decl_type.declaration.name, enum_declaration.name)) def test_free_function_type(self): @@ -419,10 +419,10 @@ def test_free_function_type(self): decl_type=declarations.typedef_t, name='function_ptr') self._test_type_composition( - function_ptr.type, + function_ptr.decl_type, declarations.pointer_t, declarations.free_function_type_t) - function_type = function_ptr.type.base + function_type = function_ptr.decl_type.base self.assertTrue( isinstance( function_type.return_type, @@ -455,11 +455,11 @@ def test_member_function_type(self): decl_type=declarations.typedef_t, name='member_function_ptr_t') self._test_type_composition( - function_ptr.type, + function_ptr.decl_type, declarations.pointer_t, declarations.member_function_type_t) - function_type = function_ptr.type.base + function_type = function_ptr.decl_type.base members_pointers = self.global_ns.class_('members_pointers_t') self.assertTrue( @@ -498,7 +498,7 @@ def test_member_variable_type(self): decl_type=declarations.typedef_t, name='member_variable_ptr_t') self._test_type_composition( - mv.type, + mv.decl_type, declarations.pointer_t, declarations.member_variable_type_t) @@ -508,10 +508,10 @@ def test_member_variable_type(self): "unable to find class('%s')" % 'members_pointers_t') self._test_type_composition( - mv.type.base, + mv.decl_type.base, declarations.member_variable_type_t, declarations.declarated_t) - mv_type = mv.type.base + mv_type = mv.decl_type.base self.assertTrue( mv_type.base.declaration is members_pointers, "member function type class should be '%s' instead of '%s'" % diff --git a/unittests/declarations_tester.py b/unittests/declarations_tester.py index 2c4e71aa..6ffc4704 100644 --- a/unittests/declarations_tester.py +++ b/unittests/declarations_tester.py @@ -52,7 +52,7 @@ def test_variables(self): "value(%s) of 'initialized' variable") % (expected_value, initialized.value)) self._test_type_composition( - initialized.type, + initialized.decl_type, declarations.const_t, declarations.long_unsigned_int_t) diff --git a/unittests/string_traits_tester.py b/unittests/string_traits_tester.py index 2bc67083..7e74f9e8 100644 --- a/unittests/string_traits_tester.py +++ b/unittests/string_traits_tester.py @@ -26,11 +26,11 @@ def setUp(self): def validate_yes(self, ns, controller): for typedef in ns.typedefs(): - self.assertTrue(controller(typedef.type)) + self.assertTrue(controller(typedef.decl_type)) def validate_no(self, ns, controller): for typedef in ns.typedefs(): - self.assertTrue(not controller(typedef.type)) + self.assertTrue(not controller(typedef.decl_type)) def test_string(self): string_traits = self.global_ns.namespace('string_traits') diff --git a/unittests/type_traits_tester.py b/unittests/type_traits_tester.py index 9f5cb35f..ee9169f0 100644 --- a/unittests/type_traits_tester.py +++ b/unittests/type_traits_tester.py @@ -46,8 +46,8 @@ def __test_type_category(self, ns_name, controller): for decl in ns_yes.declarations: if isinstance(decl, declarations.variable_t): self.assertTrue( - controller(decl.type), - er % (decl.type.decl_string, ns_name)) + controller(decl.decl_type), + er % (decl.decl_type.decl_string, ns_name)) elif isinstance(decl, declarations.calldef_t) and \ decl.name.startswith('test_'): continue diff --git a/unittests/unnamed_classes_tester.py b/unittests/unnamed_classes_tester.py index 38c5b006..d04a1dd5 100644 --- a/unittests/unnamed_classes_tester.py +++ b/unittests/unnamed_classes_tester.py @@ -36,9 +36,9 @@ def do_union_test(self, union_name, bitfields): self.assertFalse(type_traits.is_union(s2.parent)) union = s2.variable(union_name) - self.assertTrue(type_traits.is_union(union.type)) + self.assertTrue(type_traits.is_union(union.decl_type)) - union_type = type_traits.remove_declarated(union.type) + union_type = type_traits.remove_declarated(union.decl_type) self.validate_bitfields(union_type, bitfields) self.assertIsNotNone(union_type.variable('raw')) @@ -81,7 +81,7 @@ def test_anonymous_unions(self): s3_vars = ['anon_mem_c', 'anon_mem_i', 's3_mem', 's2'] for var in s3_vars: - self.assertFalse(type_traits.is_union(s3.variable(var).type)) + self.assertFalse(type_traits.is_union(s3.variable(var).decl_type)) def create_suite(): From 8e1f7adba7dd08d5098bff628534dcca6c9b23fe Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 14 Apr 2016 23:51:51 +0200 Subject: [PATCH 105/268] Avoid nbr duplication, use "in" to check the number of members --- unittests/filters_tester.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/filters_tester.py b/unittests/filters_tester.py index 23a0dc2e..437136de 100644 --- a/unittests/filters_tester.py +++ b/unittests/filters_tester.py @@ -42,7 +42,7 @@ def test_access_type(self): public_members = [d for d in public_members if not d.is_artificial] if "CastXML" in utils.xml_generator: nbr = len(public_members) - self.assertTrue(17 == nbr or 21 == nbr) + self.assertTrue(nbr in [17, 21]) if nbr == 21: # We are using llvm 3.9, see bug #32. Make sure the 4 names # are still there From 64f8894e3a68b621defe31454fb94f260ab68d01 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 15 Apr 2016 22:46:40 +0200 Subject: [PATCH 106/268] Add missing import --- pygccxml/declarations/namespace.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pygccxml/declarations/namespace.py b/pygccxml/declarations/namespace.py index 8b6772c9..1bba42f3 100644 --- a/pygccxml/declarations/namespace.py +++ b/pygccxml/declarations/namespace.py @@ -8,6 +8,7 @@ """ +import warnings from . import scopedef from . import algorithm From ccb2f7204b7d4a9f9f1dfea3320cb727cd033f78 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 15 Apr 2016 22:49:54 +0200 Subject: [PATCH 107/268] Add comments about when stuff was deprecated This will help for the documentation; and for the later cleanup. --- pygccxml/declarations/namespace.py | 2 ++ pygccxml/declarations/scopedef.py | 8 ++++++++ pygccxml/declarations/typedef.py | 11 ++++++++++- pygccxml/declarations/variable.py | 9 ++++++++- 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/pygccxml/declarations/namespace.py b/pygccxml/declarations/namespace.py index 1bba42f3..41e8593e 100644 --- a/pygccxml/declarations/namespace.py +++ b/pygccxml/declarations/namespace.py @@ -111,6 +111,8 @@ def ns(self, name=None, function=None, recursive=None): """ Deprecated method. Use the namespace() method instead. + Deprecated since v1.8.0. Will be removed in v1.9.0 + """ warnings.warn( "The ns() method is deprecated. \n" + diff --git a/pygccxml/declarations/scopedef.py b/pygccxml/declarations/scopedef.py index da1e58f6..f1556dd8 100644 --- a/pygccxml/declarations/scopedef.py +++ b/pygccxml/declarations/scopedef.py @@ -528,6 +528,10 @@ def var(self, header_dir=None, header_file=None, recursive=None): + """ + Deprecated since v1.8.0. Will be removed in v1.9.0 + + """ warnings.warn( "The var() method is deprecated. \n" + @@ -570,6 +574,10 @@ def vars( header_file=None, recursive=None, allow_empty=None): + """ + Deprecated since v1.8.0. Will be removed in v1.9.0 + + """ warnings.warn( "The vars() method is deprecated. \n" + diff --git a/pygccxml/declarations/typedef.py b/pygccxml/declarations/typedef.py index 071cd4ad..e25631ed 100644 --- a/pygccxml/declarations/typedef.py +++ b/pygccxml/declarations/typedef.py @@ -35,7 +35,11 @@ def __hash__(self): @property def type(self): - """reference to the original :class:`type `""" + """ + Deprecated since v1.8.0. Will be removed in v1.9.0 + + """ + warnings.warn( "typedef_t.type is deprecated.\n" + "Please use typedef_t.decl_type instead.", DeprecationWarning) @@ -43,6 +47,11 @@ def type(self): @type.setter def type(self, _type): + """ + Deprecated since v1.8.0. Will be removed in v1.9.0 + + """ + warnings.warn( "typedef_t.type is deprecated.\n" + "Please use typedef_t.decl_type instead.", DeprecationWarning) diff --git a/pygccxml/declarations/variable.py b/pygccxml/declarations/variable.py index 0d62d6d5..3c15948e 100644 --- a/pygccxml/declarations/variable.py +++ b/pygccxml/declarations/variable.py @@ -52,7 +52,10 @@ def __hash__(self): @property def type(self): - """reference to the variable :class:`type `""" + """ + Deprecated since v1.8.0. Will be removed in v1.9.0 + + """ warnings.warn( "variable_t.type is deprecated.\n" + "Please use variable_t.decl_type instead.", DeprecationWarning) @@ -60,6 +63,10 @@ def type(self): @type.setter def type(self, _type): + """ + Deprecated since v1.8.0. Will be removed in v1.9.0 + + """ warnings.warn( "variable_t.type is deprecated.\n" + "Please use variable_t.decl_type instead.", DeprecationWarning) From 7fd9ae6ed5da2d43245a3aa64f5815fc836f644e Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 15 Apr 2016 22:58:58 +0200 Subject: [PATCH 108/268] Remove getters/setters for compiler attribute in declarations.py These were deprecated in pygccxml v1.7.0, and definitively removed for v1.8.0 --- pygccxml/declarations/declaration.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/pygccxml/declarations/declaration.py b/pygccxml/declarations/declaration.py index 9b72566a..249c20b3 100644 --- a/pygccxml/declarations/declaration.py +++ b/pygccxml/declarations/declaration.py @@ -379,20 +379,3 @@ def i_depend_on_them(self, recursive=True): print(self) raise NotImplementedError() - - @property - def compiler(self): - """ - Compiler name + version. - - @type: str - - """ - warnings.warn( - "The compiler attribute is deprecated. \n" + - "Please use utils.xml_generator instead.", DeprecationWarning) - return self._compiler - - @compiler.setter - def compiler(self, compiler): - self._compiler = compiler From ddcda80a68ef3603b0a15d8588796ccd2941e285 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 15 Apr 2016 22:59:51 +0200 Subject: [PATCH 109/268] Remove getters/setters for gccxml_path attribute in config.py These were deprecated in pygccxml v1.7.0, and definitively removed for v1.8.0 --- pygccxml/parser/config.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index 179f189f..93c31e8e 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -238,25 +238,6 @@ def __init__( def clone(self): return copy.deepcopy(self) - @property - def gccxml_path(self): - """ - Gccxml binary location - - """ - - warnings.warn( - "gccxml_path is deprecated. \n" + - "Please use xml_generator_path instead.", DeprecationWarning) - return self.__gccxml_path - - @gccxml_path.setter - def gccxml_path(self, new_path): - warnings.warn( - "gccxml_path is deprecated. \n" + - "Please use xml_generator_path instead.", DeprecationWarning) - self.__gccxml_path = new_path - @property def xml_generator_path(self): """ From 69e71b83acb1bdca40e1beeed3e4097e570fc5af Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 15 Apr 2016 23:01:09 +0200 Subject: [PATCH 110/268] Document removal of compiler and gccxml_path --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 981c7713..45e483ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ Version 1.8.0 (not yet released) * Documentation update and cleanup +* Remove compiler attribute in declarations.py and gccxml_path from config.py + These were deprecated in pygccxml v1.7.0, and definitively removed for v1.8.0 + Version 1.7.3 ------------- From 1c0977914c7680cf5f3b14c43a9154713cfcc075 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 25 Apr 2016 21:36:23 +0200 Subject: [PATCH 111/268] Add a comment about updating version numbers for a release So this is not forgotten when done ! --- docs/releasing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/releasing.rst b/docs/releasing.rst index 723de60f..a0611eba 100644 --- a/docs/releasing.rst +++ b/docs/releasing.rst @@ -5,7 +5,7 @@ To build a new release, the following files should be modified: Modify the version numbers in: -``setup.py`` +``setup.py`` (version and download_url) ``pygccxml/__init__.py`` From d322ca21813a1492829327b401389c9d69cd2444 Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Mon, 25 Apr 2016 19:00:17 -0600 Subject: [PATCH 112/268] Fix warning in core_class_hierarchy.hpp `core_class_hierarchy.hpp` contains classes with the following inheritance hierarchy derived_private_t -> base_t multi_derived_t -> derived_private_t, base_t Since `multi_derived_t` contains `base_t` as a direct base and as a base via `derived_private_t`, this creates warnings about `base_t` being inaccessible because it's ambiguous which `base_t` instance is being referred to. Changed the inheritance hierarchy to `virtual` inheritance so that `derived_private_t` and `multi_derived_t` inheri `base_t` virtually. Now there's only a single instance of `base_t` in `multi_derived_t` and the warning is avoided. Fixes #46 Change-Id: I3a52a666460bea2cc3c66b1855288d757f93f507 --- unittests/data/core_class_hierarchy.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/unittests/data/core_class_hierarchy.hpp b/unittests/data/core_class_hierarchy.hpp index 1e1c31f2..17d97b53 100644 --- a/unittests/data/core_class_hierarchy.hpp +++ b/unittests/data/core_class_hierarchy.hpp @@ -6,8 +6,6 @@ #ifndef __core_class_hierarchy_hpp__ #define __core_class_hierarchy_hpp__ -//TODO("To add virtual inheritance case"); - namespace core{ namespace class_hierarchy{ class base_t{ @@ -24,10 +22,10 @@ class derived_public_t : public base_t{ class derived_protected_t : protected base_t{ }; -class derived_private_t : private base_t{ +class derived_private_t : private virtual base_t{ }; -class multi_derived_t : derived_private_t, protected base_t, private other_base_t{ +class multi_derived_t : derived_private_t, protected virtual base_t, private other_base_t{ }; } } From b714e5b13b0443a2412c0dff2ead14573ed38e51 Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Thu, 3 Mar 2016 01:10:14 -0700 Subject: [PATCH 113/268] Fixes for type traits handling of cv-qualified array types cv-qualified arrays were not being handled correctly by type traits manipulations functions. For instance, 'int const[N]' would not be detected as 'const'. Similar problems existed for volatile qualified arrays too. There is a difference in behavior between GCCXML and CastXML for cv-qual arrays. GCCXML produces the following nesting of types: -> volatile_t(const_t(array_t)) while CastXML produces the following nesting: -> array_t(volatile_t(const_t)) For both cases, we must unwrap the types, remove const_t, and add back the outer layers. Prior to CastXML/CastXML#55 being fixed, CastXML would incorrectly generate default constructor definitions for types with const data members. This caused pygccxml to incorrectly flag such types as trivially constructible. These tests have now been fixed, and the tests are being executed conditionally only for GCCXML (which handles them correctly), or, if CastXML is being used, then for xml_output_version >= 1.138. gccxml places cv-qualifiers to the right of the array declarator in the decl_string. For instance, given the declaration 'int const[arr[42]', the decl_string from gccxml is 'int [42] const'. Combined type_traits_castxml.hpp and type_traits_gccxml.hpp into a single file - type_traits.hpp. Change-Id: If5deaecf4cc9ab38cb8b8ac90befa9c62ebd0106 --- pygccxml/declarations/type_traits.py | 61 +- unittests/array_bug_tester.py | 59 ++ ...type_traits_gccxml.hpp => type_traits.hpp} | 74 +- unittests/data/type_traits_castxml.hpp | 866 ------------------ unittests/type_traits_tester.py | 27 +- 5 files changed, 190 insertions(+), 897 deletions(-) rename unittests/data/{type_traits_gccxml.hpp => type_traits.hpp} (92%) delete mode 100644 unittests/data/type_traits_castxml.hpp diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 83870825..7e377bef 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -284,19 +284,46 @@ def remove_reference(type): def is_const(type): """returns True, if type represents C++ const type, False otherwise""" nake_type = remove_alias(type) - return isinstance(nake_type, cpptypes.const_t) + if isinstance(nake_type, cpptypes.const_t): + return True + elif isinstance(nake_type, cpptypes.volatile_t): + return is_const(nake_type.base) + elif isinstance(nake_type, cpptypes.array_t): + return is_const(nake_type.base) + return False -def remove_const(type): +def remove_const(type_): """removes const from the type definition If type is not const type, it will be returned as is """ - nake_type = remove_alias(type) + nake_type = remove_alias(type_) if not is_const(nake_type): - return type + return type_ else: + # Handling for const and volatile qualified types. There is a + # difference in behavior between GCCXML and CastXML for cv-qual arrays. + # GCCXML produces the following nesting of types: + # -> volatile_t(const_t(array_t)) + # while CastXML produces the following nesting: + # -> array_t(volatile_t(const_t)) + # For both cases, we must unwrap the types, remove const_t, and add + # back the outer layers + if isinstance(nake_type, cpptypes.array_t): + is_v = is_volatile(nake_type) + if is_v: + result_type = nake_type.base.base.base + else: + result_type = nake_type.base.base + if is_v: + result_type = cpptypes.volatile_t(result_type) + return cpptypes.array_t(result_type, nake_type.size) + + elif isinstance(nake_type, cpptypes.volatile_t): + return cpptypes.volatile_t(nake_type.base.base) + return nake_type.base @@ -322,7 +349,13 @@ def is_same(type1, type2): def is_volatile(type): """returns True, if type represents C++ volatile type, False otherwise""" nake_type = remove_alias(type) - return isinstance(nake_type, cpptypes.volatile_t) + if isinstance(nake_type, cpptypes.volatile_t): + return True + elif isinstance(nake_type, cpptypes.const_t): + return is_volatile(nake_type.base) + elif isinstance(nake_type, cpptypes.array_t): + return is_volatile(nake_type.base) + return False def remove_volatile(type): @@ -334,6 +367,16 @@ def remove_volatile(type): if not is_volatile(nake_type): return type else: + if isinstance(nake_type, cpptypes.array_t): + is_c = is_const(nake_type) + if is_c: + base_type = nake_type.base.base.base + else: + base_type = nake_type.base.base + result_type = base_type + if is_c: + result_type = cpptypes.const_t(result_type) + return cpptypes.array_t(result_type, nake_type.size) return nake_type.base @@ -344,12 +387,12 @@ def remove_cv(type): if not is_const(nake_type) and not is_volatile(nake_type): return type result = nake_type - if is_const(nake_type): - result = nake_type.base + if is_const(result): + result = remove_const(result) if is_volatile(result): - result = result.base + result = remove_volatile(result) if is_const(result): - result = result.base + result = remove_const(result) return result diff --git a/unittests/array_bug_tester.py b/unittests/array_bug_tester.py index 8f4f31da..eb2014ff 100644 --- a/unittests/array_bug_tester.py +++ b/unittests/array_bug_tester.py @@ -55,6 +55,65 @@ def test4(self): '::xyz[2][3]' == aaaa_type.decl_string, aaaa_type.decl_string) + def test5(self): + code = 'char const arr[4] = {};' + src_reader = parser.source_reader_t(self.config) + global_ns = declarations.get_global_namespace( + src_reader.read_string(code)) + arr_type = global_ns.variable('arr').decl_type + if self.config.xml_generator == "gccxml": + self.assertTrue( + 'char[4] const' == arr_type.decl_string, + arr_type.decl_string) + else: + self.assertTrue( + 'char const[4]' == arr_type.decl_string, + arr_type.decl_string) + self.assertTrue( + declarations.is_array(arr_type)) + self.assertTrue( + declarations.is_const(arr_type)) + + def test6(self): + code = 'char volatile arr[4] = {};' + src_reader = parser.source_reader_t(self.config) + global_ns = declarations.get_global_namespace( + src_reader.read_string(code)) + arr_type = global_ns.variable('arr').decl_type + if self.config.xml_generator == "gccxml": + self.assertTrue( + 'char[4] volatile' == arr_type.decl_string, + arr_type.decl_string) + else: + self.assertTrue( + 'char volatile[4]' == arr_type.decl_string, + arr_type.decl_string) + self.assertTrue( + declarations.is_array(arr_type)) + self.assertTrue( + declarations.is_volatile(arr_type)) + + def test7(self): + code = 'char const volatile arr[4] = {};' + src_reader = parser.source_reader_t(self.config) + global_ns = declarations.get_global_namespace( + src_reader.read_string(code)) + arr_type = global_ns.variable('arr').decl_type + if self.config.xml_generator == "gccxml": + self.assertTrue( + 'char[4] const volatile' == arr_type.decl_string, + arr_type.decl_string) + else: + self.assertTrue( + 'char const volatile[4]' == arr_type.decl_string, + arr_type.decl_string) + self.assertTrue( + declarations.is_array(arr_type)) + self.assertTrue( + declarations.is_const(arr_type)) + self.assertTrue( + declarations.is_volatile(arr_type)) + def create_suite(): suite = unittest.TestSuite() diff --git a/unittests/data/type_traits_gccxml.hpp b/unittests/data/type_traits.hpp similarity index 92% rename from unittests/data/type_traits_gccxml.hpp rename to unittests/data/type_traits.hpp index 58503dcf..7991a57c 100644 --- a/unittests/data/type_traits_gccxml.hpp +++ b/unittests/data/type_traits.hpp @@ -19,6 +19,7 @@ typedef BASE volatile NAME##_volatile_t; \ typedef BASE const volatile NAME##_const_volatile_t; + struct some_struct_t{ void do_smth(); int member; @@ -47,9 +48,7 @@ struct incomplete_type; namespace is_void{ namespace yes{ - typedef void void_t; - typedef void const void_cont_t; - typedef void volatile void_volatile_t; + TYPE_PERMUTATION( void, void ) } namespace no{ typedef void* void_ptr_t; @@ -186,7 +185,6 @@ namespace yes{ typedef detail::dd_t dd_t; typedef detail::f_t f_t; typedef detail::g_t g_t; - typedef detail::const_container const_container_t; typedef detail::const_item const_item_t; @@ -287,11 +285,6 @@ namespace no{ namespace is_fundamental{ namespace yes{ -#define FUNDAMENTAL_TYPE_PERMUTATION( BASE, NAME ) \ - typedef BASE NAME##_t; \ - typedef BASE const NAME##_const_t; \ - typedef BASE volatile NAME##_volatile_t; - TYPE_PERMUTATION( void, void ) TYPE_PERMUTATION( bool, bool ) TYPE_PERMUTATION( char, char ) @@ -409,7 +402,8 @@ namespace yes{ typedef const void const_void_t; typedef const incomplete_type const_incomplete_type_t; typedef int* const int_const_t; - //TODO typedef const int& const_int_ref_t; + typedef int* volatile const int_volatile_const_t; + typedef int* const volatile int_const_volatile_t; } namespace no{ @@ -421,15 +415,24 @@ namespace no{ typedef void(*function_t)(); typedef void (some_struct_t::*member_function_t)(); typedef int int_t; + typedef const int& const_int_ref_t; } } namespace remove_const{ namespace before{ - typedef const void x1; typedef const incomplete_type x2; typedef int* const x3; typedef int* volatile x4; + typedef void const * x5; + typedef int volatile const x6; + typedef int const volatile x7; + + typedef char arr_42[42]; + typedef char const arr_c_42[42]; + typedef char volatile arr_v_42[42]; + typedef char const volatile arr_cv_42[42]; + typedef char volatile const arr_vc_42[42]; } namespace after{ @@ -437,6 +440,15 @@ namespace after{ typedef incomplete_type x2; typedef int* x3; typedef int* volatile x4; + typedef void const * x5; + typedef int volatile x6; + typedef int volatile x7; + + typedef char arr_42[42]; + typedef char arr_c_42[42]; + typedef char volatile arr_v_42[42]; + typedef char volatile arr_cv_42[42]; + typedef char volatile arr_vc_42[42]; } } namespace is_volatile{ @@ -444,9 +456,12 @@ namespace yes{ typedef void * volatile vvoid_ptr_t; typedef volatile int volatile_int_t; + typedef int* volatile const int_volatile_const_t; + typedef int* const volatile int_const_volatile_t; } namespace no{ + typedef void volatile * void_ptr_to_v_t; typedef int* int_ptr_t; typedef const int* const_int_ptr_t; typedef int* volatile_int_ptr_t; @@ -463,12 +478,30 @@ namespace before{ typedef void * volatile x1; typedef volatile int x2; typedef int* x3; + typedef void volatile * x4; + typedef int volatile const x5; + typedef int const volatile x6; + + typedef char arr_42[42]; + typedef char const arr_c_42[42]; + typedef char volatile arr_v_42[42]; + typedef char const volatile arr_cv_42[42]; + typedef char volatile const arr_vc_42[42]; } namespace after{ typedef void * x1; typedef int x2; typedef int* x3; + typedef void volatile * x4; + typedef int const x5; + typedef int const x6; + + typedef char arr_42[42]; + typedef char const arr_c_42[42]; + typedef char arr_v_42[42]; + typedef char const arr_cv_42[42]; + typedef char const arr_vc_42[42]; } } @@ -488,6 +521,12 @@ namespace before{ typedef int* const x32; typedef void(*x40)(); + + typedef char arr_42[42]; + typedef char const arr_c_42[42]; + typedef char volatile arr_v_42[42]; + typedef char const volatile arr_cv_42[42]; + typedef char volatile const arr_vc_42[42]; } namespace after{ @@ -504,6 +543,12 @@ namespace after{ typedef int* x32; typedef void(*x40)(); + + typedef char arr_42[42]; + typedef char arr_c_42[42]; + typedef char arr_v_42[42]; + typedef char arr_cv_42[42]; + typedef char arr_vc_42[42]; } } @@ -548,9 +593,6 @@ namespace yes{ namespace no{ - typedef details::const_item const_item; - typedef details::const_container const_container; - class y{ private: y(){} @@ -567,6 +609,9 @@ namespace no{ public: static singleton_t* instance(); }; + + typedef details::const_item const_item; + typedef details::const_container const_container; } } namespace has_public_constructor{ @@ -663,6 +708,7 @@ namespace yes{ const int yes2[2] = {0}; const volatile int yes3[2] = {0}; int yes4[2][3]; + int const yes5[2] = {0}; } namespace no{ diff --git a/unittests/data/type_traits_castxml.hpp b/unittests/data/type_traits_castxml.hpp deleted file mode 100644 index 29e84b19..00000000 --- a/unittests/data/type_traits_castxml.hpp +++ /dev/null @@ -1,866 +0,0 @@ -// Copyright 2014-2016 Insight Software Consortium. -// Copyright 2004-2008 Roman Yakovenko. -// Distributed under the Boost Software License, Version 1.0. -// See http://www.boost.org/LICENSE_1_0.txt - -//Almost all test cases have been taken -//from boost.type_traits (http://www.boost.org) library. - -#include -#include -#include -#include -#include -#include "noncopyable.hpp" - -#define TYPE_PERMUTATION( BASE, NAME ) \ - typedef BASE NAME##_t; \ - typedef BASE const NAME##_const_t; \ - typedef BASE volatile NAME##_volatile_t; \ - typedef BASE const volatile NAME##_const_volatile_t; - -struct some_struct_t{ - void do_smth(); - int member; -}; - -namespace is_std_ostream{ -namespace yes{ - typedef std::ostream ostream_type; -} -namespace no{ - typedef int int__; -} -} - -namespace is_std_wostream{ -namespace yes{ - typedef std::wostream wostream_type; -} -namespace no{ - typedef int int__; -} -} - - -struct incomplete_type; - -namespace is_void{ -namespace yes{ - typedef void void_t; - typedef void const void_cont_t; - typedef void volatile void_volatile_t; -} -namespace no{ - typedef void* void_ptr_t; - typedef int int_t; - typedef some_struct_t some_struct_alias_t; - typedef incomplete_type incomplete_type_alias_t; - typedef void(*function_t)(); - typedef void (some_struct_t::*member_function_t)(); -} } - -namespace is_noncopyable{ - -namespace detail{ - struct x{ - private: - x( const x& ); - x& operator=(const x& ); - }; - - struct y_type{ - union { - struct { - float x, y, z; - }; - float val[3]; - }; - - static const y_type zero; - }; - - struct instantiate_tmpls{ - instantiate_tmpls() - : v(), s(), ms() - {} - - std::vector< int > v; - std::set< std::string > s; - std::multimap< std::string, std::string > ms; - }; - - - class a_t{ - public: - - static char get_a(){ return 'a'; } - - private: - a_t(){}; - ~a_t(){}; - }; - - class b_t{ - ~b_t(){} - public: - - static char get_b(){ return 'b'; } - - }; - - class c_t : public boost::noncopyable{ - public: - static char get_c(){ return 'c'; } - - }; - - class d_t{ - private: - d_t( const d_t& ); - public: - d_t(){} - ~d_t(){} - static char get_d(){ return 'd'; } - - }; - - class dd_t : public d_t{ - public: - dd_t(){} - ~dd_t(){} - static char get_dd(){ return 'D'; } - }; - - struct e_t{ - virtual void do_smth() = 0; - private: - c_t c; - }; - - struct f_t{ - f_t() : i(0){} - virtual void do_smth() = 0; - private: - const int i; - }; - - struct g_t{ - enum E{e}; - g_t() : e_(e){} - virtual void do_smth() = 0; - private: - const E e_; - }; - - struct const_item{ const int values[10]; }; - - void test_const_item(const_item by_value); - - struct const_container{ const const_item items[10]; }; - - void test_const_container(const_container by_value); - - enum semantic{ position, normal, binormal }; - enum element_type{ float_, color, short_ }; - - struct vertex{ - protected: - unsigned short source; - size_t offset; - semantic sem; - element_type el_type; - public: - vertex( int x, int y, int z ); - - bool operator==( const vertex& ) const; - }; -} - -namespace yes{ - typedef detail::x x; - typedef detail::a_t a_t; - typedef detail::b_t b_t; - typedef detail::c_t c_t; - typedef detail::d_t d_t; - typedef detail::dd_t dd_t; - typedef detail::f_t f_t; - typedef detail::g_t g_t; - -} -namespace no{ - typedef std::string string_type; - typedef detail::y_type y_type; - typedef std::vector< int > vector_of_int_type; - typedef std::set< std::string > string_set_type; - typedef std::multimap< std::string, std::string > s2s_multimap_type; - typedef detail::vertex vertex_type; - typedef detail::const_item const_item_t; - typedef detail::const_container const_container_t; -} -} - - - -namespace is_calldef_pointer{ - -namespace details{ -struct X{ - void do_smth( int ) const; -}; - -} - -namespace yes{ - typedef void (*ff1)( int, int ); - typedef void ( details::X::*mf1)( int ) const; - - TYPE_PERMUTATION( ff1, ff1_type ); - TYPE_PERMUTATION( mf1, mf1_type ); -} - -namespace no{ - typedef int int_; -} - -} - -namespace is_integral{ -namespace yes{ - - TYPE_PERMUTATION( bool, bool ) - TYPE_PERMUTATION( char, char ) - TYPE_PERMUTATION( unsigned char, uchar ) - TYPE_PERMUTATION( short, short ) - TYPE_PERMUTATION( unsigned short, ushort ) - TYPE_PERMUTATION( int, int ) - TYPE_PERMUTATION( unsigned int, uint ) - TYPE_PERMUTATION( long, long ) - TYPE_PERMUTATION( unsigned long, ulong ) - TYPE_PERMUTATION( long long int, llint ) - TYPE_PERMUTATION( long long unsigned int, ulli ) -} -namespace no{ - typedef some_struct_t some_struct_alias_t; - typedef float* float_ptr_t; - typedef float& float_ref_t; - typedef const float& const_float_ref_t; - typedef incomplete_type incomplete_type_alias; - typedef void(*function_t)(); - typedef void (some_struct_t::*member_function_t)(); - TYPE_PERMUTATION( void, void ) - TYPE_PERMUTATION( float, float ) - TYPE_PERMUTATION( double, double ) - TYPE_PERMUTATION( long double, ldouble ) -} } - -namespace is_floating_point{ -namespace yes{ - - TYPE_PERMUTATION( float, float ) - TYPE_PERMUTATION( double, double ) - TYPE_PERMUTATION( long double, ldouble ) -} -namespace no{ - typedef some_struct_t some_struct_alias_t; - typedef float* float_ptr_t; - typedef float& float_ref_t; - typedef const float& const_float_ref_t; - typedef incomplete_type incomplete_type_alias; - typedef void(*function_t)(); - typedef void (some_struct_t::*member_function_t)(); - TYPE_PERMUTATION( void, void ) - TYPE_PERMUTATION( bool, bool ) - TYPE_PERMUTATION( char, char ) - TYPE_PERMUTATION( unsigned char, uchar ) - TYPE_PERMUTATION( short, short ) - TYPE_PERMUTATION( unsigned short, ushort ) - TYPE_PERMUTATION( int, int ) - TYPE_PERMUTATION( unsigned int, uint ) - TYPE_PERMUTATION( long, long ) - TYPE_PERMUTATION( unsigned long, ulong ) - TYPE_PERMUTATION( long long int, llint ) - TYPE_PERMUTATION( long long unsigned int, ulli ) -} } - -namespace is_fundamental{ -namespace yes{ - -#define FUNDAMENTAL_TYPE_PERMUTATION( BASE, NAME ) \ - typedef BASE NAME##_t; \ - typedef BASE const NAME##_const_t; \ - typedef BASE volatile NAME##_volatile_t; - - TYPE_PERMUTATION( void, void ) - TYPE_PERMUTATION( bool, bool ) - TYPE_PERMUTATION( char, char ) - TYPE_PERMUTATION( unsigned char, uchar ) - TYPE_PERMUTATION( short, short ) - TYPE_PERMUTATION( unsigned short, ushort ) - TYPE_PERMUTATION( int, int ) - TYPE_PERMUTATION( unsigned int, uint ) - TYPE_PERMUTATION( long, long ) - TYPE_PERMUTATION( unsigned long, ulong ) - TYPE_PERMUTATION( long long int, llint ) - TYPE_PERMUTATION( long long unsigned int, ulli ) - TYPE_PERMUTATION( float, float ) - TYPE_PERMUTATION( double, double ) - TYPE_PERMUTATION( long double, ldouble ) -} -namespace no{ - typedef some_struct_t some_struct_alias_t; - typedef float* float_ptr_t; - typedef float& float_ref_t; - typedef const float& const_float_ref_t; - typedef incomplete_type incomplete_type_alias; - typedef void(*function_t)(); - typedef void (some_struct_t::*member_function_t)(); - -} } - -namespace is_pointer{ -namespace yes{ - typedef int* int_ptr_t; - typedef const int* const_int_ptr_t; - typedef volatile int* volatile_int_ptr_t; - typedef some_struct_t* some_struct_ptr_t; - typedef int* const int_const_ptr_t; - typedef int* volatile int_volatile_ptr_t; - typedef void(*function_t)(); - typedef void (some_struct_t::*member_function_t)(); -} - -namespace no{ - typedef int int_t; - typedef int& int_ref_t; - typedef some_struct_t some_struct_alias_t; - typedef int*& int_ptr_ref_t; -} } - - -namespace remove_pointer{ -namespace before{ - typedef int* x1; - typedef const int* x2; - typedef volatile int* x3; - typedef some_struct_t* x4; - typedef int* const x5; - typedef int* volatile x6; - typedef void(*x7)(); - typedef void (some_struct_t::*x8)(); -} - -namespace after{ - typedef int x1; - typedef const int x2; - typedef volatile int x3; - typedef some_struct_t x4; - typedef int const x5; - typedef int volatile x6; - typedef void(*x7)(); - typedef void (some_struct_t::*x8)(); -} } - - -namespace is_reference{ -namespace yes{ - - typedef int& int_ref_t; - typedef const int& const_int_ref_t; - typedef int const& int_const_ref_t; - typedef some_struct_t& some_struct_ref_t; - typedef int*& int_ptr_ref_t; -} - -namespace no{ - typedef int* int_ptr_t; - typedef const int* const_int_ptr_t; - typedef volatile int* volatile_int_ptr_t; - typedef some_struct_t* some_struct_ptr_t; - typedef int* const int_const_ptr_t; - typedef int* volatile int_volatile_ptr_t; - typedef void(*function_t)(); - typedef void (some_struct_t::*member_function_t)(); - typedef int int_t; -} } - -namespace remove_reference{ -namespace before{ - - typedef int& x1; - typedef const int& x2; - typedef some_struct_t& x3; - typedef int*& x4; - typedef void (some_struct_t::*x5)(); -} - -namespace after{ - typedef int x1; - typedef const int x2; - typedef some_struct_t x3; - typedef int* x4; - typedef void (some_struct_t::*x5)(); -} } - -namespace is_const{ -namespace yes{ - - typedef const void const_void_t; - typedef const incomplete_type const_incomplete_type_t; - typedef int* const int_const_t; - //TODO typedef const int& const_int_ref_t; -} - -namespace no{ - typedef int* int_ptr_t; - typedef const int* const_int_ptr_t; - typedef volatile int* volatile_int_ptr_t; - typedef some_struct_t* some_struct_ptr_t; - typedef int* volatile int_volatile_ptr_t; - typedef void(*function_t)(); - typedef void (some_struct_t::*member_function_t)(); - typedef int int_t; -} } - -namespace remove_const{ -namespace before{ - - typedef const void x1; - typedef const incomplete_type x2; - typedef int* const x3; - typedef int* volatile x4; -} - -namespace after{ - typedef void x1; - typedef incomplete_type x2; - typedef int* x3; - typedef int* volatile x4; -} } - -namespace is_volatile{ -namespace yes{ - - typedef void * volatile vvoid_ptr_t; - typedef volatile int volatile_int_t; -} - -namespace no{ - typedef int* int_ptr_t; - typedef const int* const_int_ptr_t; - typedef int* volatile_int_ptr_t; - typedef some_struct_t* some_struct_ptr_t; - typedef int* int_volatile_ptr_t; - typedef void(*function_t)(); - typedef void (some_struct_t::*member_function_t)(); - typedef int int_t; -} } - -namespace remove_volatile{ -namespace before{ - - typedef void * volatile x1; - typedef volatile int x2; - typedef int* x3; -} - -namespace after{ - typedef void * x1; - typedef int x2; - typedef int* x3; -} } - - -namespace remove_cv{ -namespace before{ - - typedef void * volatile x10; - typedef void * const volatile x11; - typedef void * const x12; - - typedef volatile int x20; - typedef const volatile int x21; - typedef const int x22; - - typedef int* volatile x30; - typedef int* const volatile x31; - typedef int* const x32; - - typedef void(*x40)(); -} - -namespace after{ - typedef void * x10; - typedef void * x11; - typedef void * x12; - - typedef int x20; - typedef int x21; - typedef int x22; - - typedef int* x30; - typedef int* x31; - typedef int* x32; - - typedef void(*x40)(); -} } - - -namespace is_enum{ - - enum color{ red, green, blue }; - -namespace yes{ - typedef color COLOR; -} - -namespace no{ - typedef int* int_ptr_t; - typedef const int* const_int_ptr_t; - typedef int* volatile_int_ptr_t; - typedef some_struct_t* some_struct_ptr_t; - typedef int* int_volatile_ptr_t; - typedef void(*function_t)(); - typedef void (some_struct_t::*member_function_t)(); - typedef int int_t; -} } - -namespace has_trivial_constructor{ - -namespace details{ - - struct const_item{ const int values[10]; }; - - void test_const_item( const_item x = const_item() ); - - struct const_container{ const const_item items[10]; }; - - void test_const_container( const_container x = const_container() ); - -} - -namespace yes{ - struct x{ - x(){} - }; - typedef details::const_item const_item; - typedef details::const_container const_container; -} - -namespace no{ - - class y{ - private: - y(){} - }; - - class singleton_t - { - private: - static singleton_t *m_instance; - - singleton_t () {} - ~singleton_t () {} - - public: - static singleton_t* instance(); - }; -} } - -namespace has_public_constructor{ -namespace yes{ - struct x{ - x(){} - }; - - struct z{int i;}; -} - -namespace no{ - class y{ - private: - y(){} - }; -} } - -namespace has_public_destructor{ -namespace yes{ - struct x{ - ~x(){} - }; -} - -namespace no{ - class y{ - private: - ~y(){} - }; -} } - -namespace has_copy_constructor{ -namespace yes{ - struct x{ - x(const x&){} - }; - typedef is_noncopyable::detail::vertex vertex_type; -} - -namespace no{ - class y{ - private: - y(const y&){} - }; -} } - -namespace is_base_and_derived{ -namespace yes{ - struct base{}; - struct derived : public base {}; -} - -namespace no{ - struct unrelated1{}; - struct unrelated2{}; -} } - -namespace has_any_non_copyconstructor{ -namespace yes{ - struct x{ - x(int){} - }; -} - -namespace no{ - class y{ - private: - y(){} - }; -} } - -namespace is_unary_operator{ - -struct dummy{ - bool operator!(){ return true; } - int operator++(){ return 0; } - int operator+(const dummy& ){ return 0; } -}; - -inline int operator++( dummy& ){ return 0; } -inline int operator*( const dummy&, const dummy& ){ return 0; } - -dummy& operator+=( dummy& x, const dummy& ){ - return x; -} - -} - -namespace is_array{ - -namespace yes{ - int yes1[2]; - const int yes2[2] = {0}; - const volatile int yes3[2] = {0}; - int yes4[2][3]; -} - -namespace no{ - typedef int no1; - typedef int* no2; - typedef const int* no3; - typedef const volatile int* no4; - typedef int*const no5; - typedef const int*volatile no6; - typedef const volatile int*const no7; - typedef void( * no8)( const int[2] ); -} } - -namespace is_convertible{ - -template -struct convertible_from{ - convertible_from(T); -}; - -template -struct convertible_to{ - operator T (); - -}; - -struct base{}; - -struct other{}; - -struct derived : base {}; - -struct derived_protected : protected base {}; - -struct derived_private : private base {}; - -struct base2{}; - -struct middle2 : virtual base2 {}; - -struct derived2 : middle2 {}; - -enum fruit{ apple }; - -template < typename source_type_, typename target_type_, int value_ > -struct tester_t{ - typedef source_type_ source_type; - typedef target_type_ target_type; - enum expected{ value=value_ }; -}; - -template < typename source_type_, typename target_type_, int value_ > -struct tester_source_t{ - typedef source_type_ source_type; - typedef target_type_ target_type; - enum expected{ value=value_ }; - -private: - enum { sizeof_source = sizeof( source_type ) }; -}; - -template < typename source_type_, typename target_type_, int value_ > -struct tester_target_t{ - typedef source_type_ source_type; - typedef target_type_ target_type; - enum expected{ value=value_ }; - -private: - enum { sizeof_target = sizeof( target_type ) }; -}; - -template < typename source_type_, typename target_type_, int value_ > -struct tester_both_t{ - typedef source_type_ source_type; - typedef target_type_ target_type; - enum expected{ value=value_ }; - -private: - enum { sizeof_source = sizeof( source_type ) }; - enum { sizeof_target = sizeof( target_type ) }; -}; - -struct x1 : public tester_t< const int *, int*, false >{}; -struct x2 : public tester_t< int *, const int*, true >{}; -struct x3 : public tester_t< const int&, int&, false >{}; -struct x4 : public tester_t< const int&, int, true >{}; -struct x5 : public tester_t< const int&, char, true >{}; -struct x6 : public tester_t< const int&, char&, false >{}; -struct x7 : public tester_t< const int&, char*, false >{}; -struct x8 : public tester_t< int&, const int&, true >{}; -struct x9 : public tester_t< int *, const int*, true >{}; -struct x10 : public tester_t< int&, const int&, true >{}; -struct x11 : public tester_t< float, int, true >{}; -struct x12 : public tester_t< double, int, true >{}; -struct x13 : public tester_t< double, float, true >{}; -struct x14 : public tester_t< long, int, true >{}; -struct x15 : public tester_t< int, char, true >{}; -struct x16 : public tester_t< long long, int, true >{}; -struct x17 : public tester_t< long long, char, true >{}; -struct x18 : public tester_t< long long, float, true >{}; -struct x19 : public tester_t< float, int, true >{}; -struct x20 : public tester_t< float, void, false >{}; -struct x21 : public tester_t< void, void, true >{}; -struct x22 : public tester_t< double, void*, true >{}; -struct x23 : public tester_t< double, int*, false >{}; -struct x24 : public tester_t< int, int*, false >{}; -struct x25 : public tester_t< const int, int*, false >{}; -struct x26 : public tester_t< const int&, int*, false >{}; -struct x27 : public tester_t< double*, int*, false >{}; -struct x28 : public tester_source_t< convertible_to, int, true >{}; -struct x29 : public tester_target_t< int, convertible_to, false >{}; -struct x30 : public tester_source_t< convertible_to, float, true >{}; -struct x31 : public tester_target_t< float, convertible_to, false >{}; -struct x32 : public tester_source_t< convertible_to, float, true >{}; -struct x33 : public tester_target_t< float, convertible_to, false >{}; -struct x34 : public tester_source_t< convertible_to, float, true >{}; -struct x35 : public tester_target_t< float, convertible_to, false >{}; -struct x36 : public tester_source_t< convertible_to, float, true >{}; -struct x37 : public tester_target_t< float, convertible_to, false >{}; -struct x38 : public tester_source_t< convertible_to, float, true >{}; -struct x39 : public tester_target_t< float, convertible_to, false >{}; -struct x40 : public tester_source_t< convertible_to, char, true >{}; -struct x41 : public tester_source_t< convertible_to, char, true >{}; -struct x42 : public tester_source_t< convertible_to, char, true >{}; -struct x43 : public tester_source_t< convertible_to, float&, true >{}; -struct x44 : public tester_source_t< convertible_to, float const&, true >{}; -struct x45 : public tester_source_t< convertible_to, float&, true >{}; -struct x46 : public tester_source_t< convertible_to, float const&, true >{}; -struct x47 : public tester_source_t< convertible_to, float&, false >{}; -struct x48 : public tester_target_t< float, convertible_from, true >{}; -struct x49 : public tester_target_t< float, convertible_from, true >{}; -struct x50 : public tester_target_t< float, convertible_from, true >{}; -struct x51 : public tester_target_t< float, convertible_from, true >{}; -struct x52 : public tester_target_t< float, convertible_from, true >{}; -struct x53 : public tester_target_t< float, convertible_from, false >{}; -struct x54 : public tester_target_t< char, convertible_from, true >{}; -struct x55 : public tester_target_t< char, convertible_from, true >{}; -struct x56 : public tester_target_t< char, convertible_from, true >{}; -struct x57 : public tester_target_t< float&, convertible_from , true >{}; -struct x58 : public tester_target_t< float const&, convertible_from , true >{}; -struct x59 : public tester_target_t< float&, convertible_from , true >{}; -struct x60 : public tester_target_t< float const&, convertible_from, true >{}; -struct x61 : public tester_target_t< float&, convertible_from, true >{}; -struct x62 : public tester_target_t< int, convertible_from, true >{}; -struct x63 : public tester_t< const int*, int[3], false >{}; -struct x64 : public tester_t< int(&)[4], const int*, true >{}; -struct x65 : public tester_t< int(&)(int), int(*)(int), true >{}; -struct x66 : public tester_t< int[2], int*, true >{}; -struct x67 : public tester_t< int[2], const int*, true >{}; -struct x68 : public tester_t< const int[2], int*, false >{}; -struct x69 : public tester_t< int*, int[3], false >{}; -struct x70 : public tester_t< float, int&, false >{}; -struct x71 : public tester_t< float, const int&, true >{}; -struct x72 : public tester_t< other, void*, true >{}; -struct x73 : public tester_t< int, void*, false >{}; -struct x74 : public tester_t< fruit, void*, false >{}; -struct x75 : public tester_t< other, int*, false >{}; -struct x76 : public tester_t< other*, int*, false >{}; -struct x77 : public tester_t< fruit, int, true >{}; -struct x78 : public tester_t< fruit, double, true >{}; -struct x79 : public tester_t< fruit, char, true >{}; -struct x80 : public tester_t< fruit, wchar_t, true >{}; -struct x81 : public tester_t< derived, base, true >{}; -struct x82 : public tester_t< derived, derived, true >{}; -struct x83 : public tester_t< base, base, true >{}; -struct x84 : public tester_t< base, derived, false >{}; -struct x85 : public tester_t< other, base, false >{}; -struct x86 : public tester_t< middle2, base2, true >{}; -struct x87 : public tester_t< derived2, base2, true >{}; -struct x88 : public tester_t< derived*, base*, true >{}; -struct x89 : public tester_t< base*, derived*, false >{}; -struct x90 : public tester_t< derived&, base&, true >{}; -struct x91 : public tester_t< base&, derived&, false >{}; -struct x92 : public tester_t< const derived*, const base*, true >{}; -struct x93 : public tester_t< const base*, const derived*, false >{}; -struct x94 : public tester_t< const derived&, const base&, true >{}; -struct x95 : public tester_t< const base&, const derived&, false >{}; -struct x96 : public tester_t< derived_private, base, false >{}; -struct x97 : public tester_t< derived_protected, base, true >{}; -struct x98 : public tester_t< derived_protected, derived_private, false >{}; - - - -// : public tester_t< test_abc3, const test_abc1&, true >{}; -// : public tester_t< non_int_pointer, void*, true >{}; -// : public tester_t< test_abc1&, test_abc2&, false >{}; -// : public tester_t< test_abc1&, int_constructible, false >{}; -// : public tester_t< int_constructible, test_abc1&, false >{}; -// : public tester_t< test_abc1&, test_abc2, false >{}; - -//~ : public tester_t< polymorphic_derived1,polymorphic_base, true >{}; -//~ : public tester_t< polymorphic_derived2,polymorphic_base, true >{}; -//~ : public tester_t< polymorphic_base,polymorphic_derived1, false >{}; -//~ : public tester_t< polymorphic_base,polymorphic_derived2, false >{}; -//~ #ifndef BOOST_NO_IS_ABSTRACT -//~ : public tester_t< test_abc1,test_abc1, false >{}; -//~ : public tester_t< Base,test_abc1, false >{}; -//~ : public tester_t< polymorphic_derived2,test_abc1, false >{}; -//~ : public tester_t< int,test_abc1, false >{}; -//~ #endif - - -} diff --git a/unittests/type_traits_tester.py b/unittests/type_traits_tester.py index ee9169f0..93200abd 100644 --- a/unittests/type_traits_tester.py +++ b/unittests/type_traits_tester.py @@ -18,7 +18,7 @@ class tester_t(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) - self.header = 'type_traits_' + self.config.xml_generator + '.hpp' + self.header = 'type_traits.hpp' self.declarations = None def setUp(self): @@ -60,6 +60,13 @@ def __test_type_category(self, ns_name, controller): decl.name.startswith('test_'): continue + if ("CastXML" in utils.xml_generator and + utils.xml_output_version < 1.138 and + decl.name in ['const_item', 'const_container']): + # Skip this test to workaround CastXML bug. + # See https://github.com/CastXML/CastXML/issues/55 + continue + self.assertFalse( controller(decl), er % (decl.decl_string, ns_name)) @@ -94,8 +101,11 @@ def __test_type_transformation(self, ns_name, transformer): declarations.is_same( transformed, tafter), - ("there is a difference between expected type and result. " + - "typedef name: %s") % tbefore.decl_string) + ("there is a difference between expected type({0}) " + + "and result({1}). typedef name: {2}").format( + declarations.remove_declarated(tafter).decl_string, + declarations.remove_declarated(transformed).decl_string, + tbefore.decl_string)) def test_is_enum(self): self.__test_type_category('is_enum', declarations.is_enum) @@ -357,12 +367,13 @@ def test(self): code = "struct const_item{ const int values[10]; };" global_ns = parser.parse_string(code, config)[0] ci = global_ns.class_('const_item') - if 'CastXML' in utils.xml_generator: - # Constructor, copy constructor, destructor, variable - self.assertTrue(len(ci.declarations) == 4) - else: + if ("CastXML" not in utils.xml_generator or + utils.xml_output_version >= 1.138): + # Prior to version 1.138, CastXML would incorrect create a default + # constructor definition. + # See https://github.com/CastXML/CastXML/issues/55 # Copy constructor, destructor, variable - self.assertTrue(len(ci.declarations) == 3) + self.assertEqual(len(ci.declarations), 3) # class tester_diff_t( parser_test_case.parser_test_case_t ): # COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE From cb3e53be343fd83e07f5e1985dc46f7a7da9b6b7 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 26 Apr 2016 22:40:39 +0200 Subject: [PATCH 114/268] Remove unnecessary try/catch block The exception clause is too broad, as it is catching all exceptions. The git history does not help to understand why that try/catch block is there. If there is an exception, we want to know what it is and act accordingly. I do not expect any exception in that code block (even if an IOError is still possible, but this could happen at a lot of places in the code). --- pygccxml/parser/source_reader.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 4c9f638e..a29fffd5 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -455,16 +455,11 @@ def __produce_full_file(self, file_path): file_path = file_path.replace(r'\/', os.path.sep) if os.path.isabs(file_path): return file_path - try: - abs_file_path = os.path.realpath( - os.path.join( - self.__config.working_directory, - file_path)) - if os.path.exists(abs_file_path): - return os.path.normpath(abs_file_path) - return file_path - except Exception: - return file_path + abs_file_path = os.path.realpath( + os.path.join(self.__config.working_directory, file_path)) + if os.path.exists(abs_file_path): + return os.path.normpath(abs_file_path) + return file_path def __parse_xml_file(self, xml_file): scanner_ = scanner_t(xml_file, self.__decl_factory, self.__config) From 3928af320f653c514d4a938805756a46f15f4fcb Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 26 Apr 2016 23:14:58 +0200 Subject: [PATCH 115/268] Deprecate etree_scanner_t and etree_saxifier_t classes The most efficient xml scanner class is the ietree_scanner_t class, which is the one used since many years now. --- CHANGELOG.md | 6 ++++++ pygccxml/parser/etree_scanner.py | 19 ++++++++++++++----- pygccxml/parser/source_reader.py | 6 +----- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45e483ec..39baa828 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ Version 1.8.0 (not yet released) * find_xml_generator will now look for castxml first * Deprecate the ns() method. The namespace() method can be used instead. + ns() will be removed in 1.9.0. + +* Deprecate etree_scanner_t and etree_saxifier_t classes. + The most efficient xml scanner class is the ietree_scanner_t class, which + is the one used since many years now. The two other classes will be removed + in 1.9.0. * General code style overhaul (with the help of quantifiedcode.com) diff --git a/pygccxml/parser/etree_scanner.py b/pygccxml/parser/etree_scanner.py index fb3204b7..72d4ed66 100644 --- a/pygccxml/parser/etree_scanner.py +++ b/pygccxml/parser/etree_scanner.py @@ -3,6 +3,7 @@ # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt +import warnings from . import scanner # keep py2exe happy @@ -14,6 +15,11 @@ class etree_saxifier_t(object): def __init__(self, etree, handler): + """ + Deprecated since 1.8.0. Will be removed in 1.9.0. + + """ + warnings.warn("etree_saxifier_t is deprecated.\n", DeprecationWarning) self.__root_elem = etree.getroot() self.__handler = handler @@ -32,6 +38,13 @@ def __recursive_saxify(self, element): class etree_scanner_t(scanner.scanner_t): def __init__(self, xml_file, decl_factory, *args): + """ + Deprecated since 1.8.0. Will be removed in 1.9.0. + + """ + warnings.warn( + "etree_scanner_t is deprecated.\n" + + "Please use ietree_scanner_t instead.", DeprecationWarning) scanner.scanner_t.__init__(self, xml_file, decl_factory, *args) def read(self): @@ -48,9 +61,7 @@ def __init__(self, xml_file, decl_factory, *args): def read(self): context = ElementTree.iterparse( self.xml_file, - events=( - "start", - "end")) + events=("start", "end")) for event, elem in context: if event == 'start': self.startElement(elem.tag, elem.attrib) @@ -58,5 +69,3 @@ def read(self): self.endElement(elem.tag) elem.clear() self.endDocument() - -etree_scanner_t = ietree_scanner_t diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index a29fffd5..56130555 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -11,11 +11,7 @@ import subprocess import pygccxml.utils -try: # select the faster xml parser - from .etree_scanner import etree_scanner_t as scanner_t -except ImportError: - from .scanner import scanner_t - +from .etree_scanner import ietree_scanner_t as scanner_t from . import declarations_cache from pygccxml import utils from pygccxml import declarations From c9192fb40aa9f6fa44ca7e16a9258f97cb156d5c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 26 Apr 2016 23:17:47 +0200 Subject: [PATCH 116/268] Do not shadow names from outer scope This was not breaking anything, but is considered better style. --- pygccxml/parser/source_reader.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 56130555..db4eb950 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -370,14 +370,14 @@ def read_cpp_source_file(self, source_file): try: ffname = self.__file_full_name(source_file) self.logger.debug("Reading source file: [%s]." % ffname) - declarations = self.__dcache.cached_value(ffname, self.__config) - if not declarations: + decls = self.__dcache.cached_value(ffname, self.__config) + if not decls: self.logger.debug( "File has not been found in cache, parsing...") xml_file = self.create_xml_file(ffname) - declarations, files = self.__parse_xml_file(xml_file) + decls, files = self.__parse_xml_file(xml_file) self.__dcache.update( - ffname, self.__config, declarations, files) + ffname, self.__config, decls, files) else: self.logger.debug( ("File has not been changed, reading declarations " + @@ -389,7 +389,7 @@ def read_cpp_source_file(self, source_file): if xml_file: pygccxml.utils.remove_file_no_raise(xml_file, self.__config) - return declarations + return decls def read_xml_file(self, xml_file): """ @@ -406,16 +406,16 @@ def read_xml_file(self, xml_file): ffname = self.__file_full_name(xml_file) self.logger.debug("Reading xml file: [%s]" % xml_file) - declarations = self.__dcache.cached_value(ffname, self.__config) - if not declarations: + decls = self.__dcache.cached_value(ffname, self.__config) + if not decls: self.logger.debug("File has not been found in cache, parsing...") - declarations, files = self.__parse_xml_file(ffname) - self.__dcache.update(ffname, self.__config, declarations, []) + decls, files = self.__parse_xml_file(ffname) + self.__dcache.update(ffname, self.__config, decls, []) else: self.logger.debug( "File has not been changed, reading declarations from cache.") - return declarations + return decls def read_string(self, content): """ @@ -429,13 +429,13 @@ def read_string(self, content): f.write(content) try: - declarations = self.read_file(header_file) + decls = self.read_file(header_file) except Exception: pygccxml.utils.remove_file_no_raise(header_file, self.__config) raise pygccxml.utils.remove_file_no_raise(header_file, self.__config) - return declarations + return decls def __file_full_name(self, file): if os.path.isfile(file): From b5a88ef0d2ce5406a704ea065866bf02a871a1ee Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 26 Apr 2016 23:23:40 +0200 Subject: [PATCH 117/268] Use triple quotes for docstrings --- pygccxml/declarations/calldef.py | 2 +- pygccxml/declarations/class_declaration.py | 28 +++++++++++----------- pygccxml/declarations/cpptypes.py | 21 +++++++++------- pygccxml/declarations/enumeration.py | 4 ++-- pygccxml/declarations/typedef.py | 4 ++-- pygccxml/parser/config.py | 2 +- pygccxml/parser/declarations_cache.py | 2 +- pygccxml/parser/scanner.py | 6 ++--- 8 files changed, 36 insertions(+), 33 deletions(-) diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index 92e5c154..d0b388ad 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -685,7 +685,7 @@ def __init__(self): @property def symbol(self): - "operator's symbol. For example: operator+, symbol is equal to '+'" + """operator's symbol. For example: operator+, symbol is equal to '+'""" return self.name[operator_t.OPERATOR_WORD_LEN:].strip() # Third level in hierarchy of calldef diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 1476b4d7..1fed376c 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -95,7 +95,7 @@ def __lt__(self, other): @property def related_class(self): - "reference to base or derived :class:`class `" + """reference to base or derived :class:`class `""" return self._related_class @related_class.setter @@ -116,7 +116,7 @@ def access(self, new_access): # TODO: Why is there an access_type / access which are the same ? @property def access_type(self): - "describes :class:`hierarchy type `" + """describes :class:`hierarchy type `""" return self.access @access_type.setter @@ -127,7 +127,7 @@ def access_type(self, new_access_type): # information @property def is_virtual(self): - "indicates whether the inheritance is virtual or not" + """indicates whether the inheritance is virtual or not""" return self._is_virtual @is_virtual.setter @@ -156,7 +156,7 @@ def i_depend_on_them(self, recursive=True): @property def aliases(self): - "List of :class:`aliases ` to this instance" + """List of :class:`aliases ` to this instance""" return self._aliases @aliases.setter @@ -301,7 +301,7 @@ def __hash__(self): @property def class_type(self): - "describes class :class:`type `" + """describes class :class:`type `""" return self._class_type @class_type.setter @@ -312,7 +312,7 @@ def class_type(self, new_class_type): @property def bases(self): - "list of :class:`base classes `" + """list of :class:`base classes `""" return self._bases @bases.setter @@ -335,7 +335,7 @@ def recursive_bases(self): @property def derived(self): - "list of :class:`derived classes `" + """list of :class:`derived classes `""" return self._derived @derived.setter @@ -358,7 +358,7 @@ def recursive_derived(self): @property def is_abstract(self): - "describes whether class abstract or not" + """describes whether class abstract or not""" return self._is_abstract @is_abstract.setter @@ -367,7 +367,7 @@ def is_abstract(self, is_abstract): @property def public_members(self): - "list of all public :class:`members `" + """list of all public :class:`members `""" return self._public_members @public_members.setter @@ -376,7 +376,7 @@ def public_members(self, new_public_members): @property def private_members(self): - "list of all private :class:`members `" + """list of all private :class:`members `""" return self._private_members @private_members.setter @@ -385,7 +385,7 @@ def private_members(self, new_private_members): @property def protected_members(self): - "list of all protected :class:`members `" + """list of all protected :class:`members `""" return self._protected_members @protected_members.setter @@ -394,7 +394,7 @@ def protected_members(self, new_protected_members): @property def aliases(self): - "List of :class:`aliases ` to this instance" + """List of :class:`aliases ` to this instance""" return self._aliases @aliases.setter @@ -403,7 +403,7 @@ def aliases(self, new_aliases): @property def byte_size(self): - "Size of this class in bytes @type: int" + """Size of this class in bytes @type: int""" return self._byte_size @byte_size.setter @@ -412,7 +412,7 @@ def byte_size(self, new_byte_size): @property def byte_align(self): - "Alignment of this class in bytes @type: int" + """Alignment of this class in bytes @type: int""" return self._byte_align @byte_align.setter diff --git a/pygccxml/declarations/cpptypes.py b/pygccxml/declarations/cpptypes.py index e8d4a40d..60e7c587 100644 --- a/pygccxml/declarations/cpptypes.py +++ b/pygccxml/declarations/cpptypes.py @@ -57,13 +57,13 @@ def _clone_impl(self): raise NotImplementedError() def clone(self): - "returns new instance of the type" + """returns new instance of the type""" answer = self._clone_impl() return answer @property def byte_size(self): - "Size of this type in bytes @type: int" + """Size of this type in bytes @type: int""" return self._byte_size @byte_size.setter @@ -72,7 +72,7 @@ def byte_size(self, new_byte_size): @property def byte_align(self): - "Alignment of this type in bytes @type: int" + """Alignment of this type in bytes @type: int""" return self._byte_align @byte_align.setter @@ -105,8 +105,11 @@ def _clone_impl(self): class unknown_t(type_t): + """ + type, that represents all C++ types, + that could not be parsed by GCC-XML - "type, that represents all C++ types, that could not be parsed by GCC-XML" + """ def __init__(self): type_t.__init__(self) @@ -499,7 +502,7 @@ def __init__(self, base): @property def base(self): - "reference to internal/base class" + """reference to internal/base class""" return self._base @base.setter @@ -598,7 +601,7 @@ def __init__(self, base, size): @property def size(self): - "returns array size" + """returns array size""" return self._size @size.setter @@ -881,7 +884,7 @@ def __init__(self, declaration): @property def declaration(self): - "reference to :class:`declaration_t`" + """reference to :class:`declaration_t`""" return self._declaration @declaration.setter @@ -899,12 +902,12 @@ def _clone_impl(self): @property def byte_size(self): - "Size of this type in bytes @type: int" + """Size of this type in bytes @type: int""" return self._declaration.byte_size @property def byte_align(self): - "alignment of this type in bytes @type: int" + """alignment of this type in bytes @type: int""" return self._declaration.byte_align diff --git a/pygccxml/declarations/enumeration.py b/pygccxml/declarations/enumeration.py index 6b1c4f64..c841f180 100644 --- a/pygccxml/declarations/enumeration.py +++ b/pygccxml/declarations/enumeration.py @@ -134,7 +134,7 @@ def i_depend_on_them(self, recursive=True): @property def byte_size(self): - "Size of this class in bytes @type: int" + """Size of this class in bytes @type: int""" return self._byte_size @byte_size.setter @@ -143,7 +143,7 @@ def byte_size(self, new_byte_size): @property def byte_align(self): - "Alignment of this class in bytes @type: int" + """Alignment of this class in bytes @type: int""" return self._byte_align @byte_align.setter diff --git a/pygccxml/declarations/typedef.py b/pygccxml/declarations/typedef.py index e25631ed..b73c68de 100644 --- a/pygccxml/declarations/typedef.py +++ b/pygccxml/declarations/typedef.py @@ -71,10 +71,10 @@ def i_depend_on_them(self, recursive=True): @property def byte_size(self): - "Size of this type in bytes @type: int" + """Size of this type in bytes @type: int""" return self._type.byte_size @property def byte_align(self): - "alignment of this type in bytes @type: int" + """alignment of this type in bytes @type: int""" return self._type.byte_align diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index 93c31e8e..3fb1aca3 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -157,7 +157,7 @@ def compiler_path(self, compiler_path): @property def cflags(self): - "additional flags to pass to compiler" + """additional flags to pass to compiler""" return self.__cflags @cflags.setter diff --git a/pygccxml/parser/declarations_cache.py b/pygccxml/parser/declarations_cache.py index ce75caa7..0ec0103a 100644 --- a/pygccxml/parser/declarations_cache.py +++ b/pygccxml/parser/declarations_cache.py @@ -200,7 +200,7 @@ def __init__(self, name): @staticmethod def __load(file_name): - " Load pickled cache from file and return the object. " + """ Load pickled cache from file and return the object. """ if os.path.exists(file_name) and not os.path.isfile(file_name): raise RuntimeError( diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index ea279b7f..4ba3d75c 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -324,19 +324,19 @@ def __read_access(self, attrs): declarations.ACCESS_TYPES.PUBLIC) def __read_byte_size(self, decl, attrs): - "Using duck typing to set the size instead of in constructor" + """Using duck typing to set the size instead of in constructor""" size = attrs.get(XML_AN_SIZE, 0) # Make sure the size is in bytes instead of bits decl.byte_size = int(size) / 8 def __read_byte_offset(self, decl, attrs): - "Using duck typing to set the offset instead of in constructor" + """Using duck typing to set the offset instead of in constructor""" offset = attrs.get(XML_AN_OFFSET, 0) # Make sure the size is in bytes instead of bits decl.byte_offset = int(offset) / 8 def __read_byte_align(self, decl, attrs): - "Using duck typing to set the alignment" + """Using duck typing to set the alignment""" align = attrs.get(XML_AN_ALIGN, 0) # Make sure the size is in bytes instead of bits decl.byte_align = int(align) / 8 From aa2152163776f9874edfd73e977f726d3de0c54d Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 26 Apr 2016 23:25:28 +0200 Subject: [PATCH 118/268] Use augmented assignment --- unittests/pep8_tester.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/unittests/pep8_tester.py b/unittests/pep8_tester.py index 373ede57..73685dd5 100644 --- a/unittests/pep8_tester.py +++ b/unittests/pep8_tester.py @@ -30,7 +30,7 @@ def test_pep8_conformance_pygccxml(self): # Get the path to current directory path = os.path.dirname(os.path.realpath(__file__)) - path = path + "/../pygccxml/" + path += "/../pygccxml/" self.run_check(path) @@ -44,7 +44,7 @@ def test_pep8_conformance_example(self): # Get the path to current directory path = os.path.dirname(os.path.realpath(__file__)) - path = path + "/../docs/examples/" + path += "/../docs/examples/" # Find all the examples files file_paths = [] @@ -65,7 +65,7 @@ def test_pep8_conformance_setup(self): # Get the path to current directory path = os.path.dirname(os.path.realpath(__file__)) - path = path + "/../setup.py" + path += "/../setup.py" self.run_check(path) From a18e7c6898f6599bf025a891e6fdb2091de54e52 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 27 Apr 2016 00:06:49 +0200 Subject: [PATCH 119/268] Uniformise some docstrings for pep257 --- pygccxml/utils/utils.py | 63 ++++++++--------------------------------- 1 file changed, 12 insertions(+), 51 deletions(-) diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index 18ea1f30..c67c1e31 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -3,10 +3,7 @@ # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt -""" -Logger classes and a few convenience methods. - -""" +"""Logger classes and a few convenience methods.""" import os import sys @@ -16,16 +13,15 @@ import subprocess -def is_str(s): +def is_str(string): """ Python 2 and 3 compatible string checker. """ - if sys.version_info >= (3, 0): - return isinstance(s, str) + return isinstance(string, str) else: - return isinstance(s, basestring) + return isinstance(string, basestring) def find_xml_generator(name=None): @@ -40,7 +36,6 @@ def find_xml_generator(name=None): raises an exception. """ - if platform.system() == "Windows": command = "where" else: @@ -65,11 +60,7 @@ def find_xml_generator(name=None): def _create_logger_(name): - """ - Implementation detail, creates a logger. - - """ - + """Implementation detail, creates a logger.""" logger = logging.getLogger(name) handler = logging.StreamHandler() handler.setFormatter(logging.Formatter('%(levelname)s %(message)s')) @@ -79,10 +70,7 @@ def _create_logger_(name): class loggers(object): - """ - Class-namespace, defines a few loggers classes, used in the project. - - """ + """Class-namespace, defines a few loggers classes, used in the project.""" cxx_parser = _create_logger_('pygccxml.cxx_parser') """ @@ -137,21 +125,13 @@ class loggers(object): @staticmethod def set_level(level): - """ - Set the same logging level for all the loggers at once. - - """ - + """Set the same logging level for all the loggers at once.""" for logger in loggers.all_loggers: logger.setLevel(level) def remove_file_no_raise(file_name, config): - """ - Removes file from disk if exception is raised. - - """ - + """Removes file from disk if exception is raised.""" # The removal can be disabled by the config for debugging purposes. if config.keep_xml: return True @@ -173,7 +153,6 @@ def create_temp_file_name(suffix, prefix=None, dir=None): function tempfile.mkstemp. """ - if not prefix: prefix = tempfile.gettempprefix() fd, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir) @@ -183,11 +162,7 @@ def create_temp_file_name(suffix, prefix=None, dir=None): def normalize_path(some_path): - """ - Return os.path.normpath(os.path.normcase(some_path)) - - """ - + """Return os.path.normpath(os.path.normcase(some_path)).""" return os.path.normpath(os.path.normcase(some_path)) @@ -199,7 +174,6 @@ def contains_parent_dir(fpath, dirs): this function. """ - # Note: this function is used nowhere in pygccxml but is used # at least by pypluplus; so it should stay here. @@ -207,11 +181,7 @@ def contains_parent_dir(fpath, dirs): def _f(fpath, dir_): - """ - Helper function for contains_parent_dir function. - - """ - + """Helper function for contains_parent_dir function.""" return fpath.startswith(dir_) @@ -222,7 +192,6 @@ def get_architecture(): The guess is based on maxint. """ - if sys.maxsize == 2147483647: return 32 elif sys.maxsize == 9223372036854775807: @@ -232,10 +201,7 @@ def get_architecture(): class cached(property): - """ - Convert a method into a cached attribute. - - """ + """Convert a method into a cached attribute.""" # The following code is cut-and-paste from this post: # http://groups.google.com/group/comp.lang.python/browse_thread/ @@ -301,11 +267,7 @@ def name_of(cls, enum_numeric_value): class native_compiler(object): - """ - Provides information about the compiler which was used to build the - Python executable - - """ + """Get the compiler used to build the Python executable.""" @staticmethod def get_version(): @@ -338,7 +300,6 @@ def get_tr1(name): appending to search patterns. """ - tr1 = "" if "tr1" in name: tr1 = "tr1::" From 1bef7a3f807449775068845bf8bb75755f41c275 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 28 Apr 2016 22:57:47 +0200 Subject: [PATCH 120/268] Deprecate native_compiler methods native_compiler.get_version() and native_compiler.get_gccxml_compiler() were used to get the compiler which was used to compile the Python executable. The get_gccxml_compiler() does not make sense anymore, as gccxml is slowly being phased out. These methods only work under windows with msvc. They are not tested by the current tests. Also, their contribution to pygccxml are low as they are currently only called once in a test that is not run... I am aware that pyplusplus is using these methods (but only twice). To reduce the maintenance burden on pygccxml, if somebody needs these methods he will need to copy them from here and put them in his code. --- pygccxml/utils/utils.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index 184f8eeb..54c92210 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -11,6 +11,7 @@ import logging import tempfile import subprocess +import warnings def is_str(string): @@ -274,6 +275,15 @@ class native_compiler(object): @staticmethod def get_version(): + """ + Get the version of the compiler used to build the Python executable. + + Deprecated since 1.8.0. Will be removed in 1.9.0. + + """ + warnings.warn( + "native_compiler.get_version is deprecated.\n", + DeprecationWarning) if 'nt' != os.name: return None # not implemented yet else: @@ -282,6 +292,14 @@ def get_version(): @staticmethod def get_gccxml_compiler(): + """Get a modified version string of the compiler. + + Deprecated since 1.8.0. Will be removed in 1.9.0. + + """ + warnings.warn( + "native_compiler.get_gccxml_compiler is deprecated.\n", + DeprecationWarning) compiler = native_compiler.get_version() if not compiler: return None From e293865472f8be591e326d9184200d0679f73d39 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 28 Apr 2016 23:31:00 +0200 Subject: [PATCH 121/268] Enable napoleon and document methods The napoleon extension allows to create documentation using the Google doctoring style. This style is preferred as shorter to write. This commit is also a test to see if readthedocs copes with this change --- docs/conf.py | 1 + pygccxml/utils/utils.py | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 06d55402..f6c19689 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -31,6 +31,7 @@ # ones. extensions = [ 'sphinx.ext.autodoc', + 'sphinxcontrib.napoleon' ] # Add any paths that contain templates here, relative to this directory. diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index 54c92210..3318bde6 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -280,6 +280,10 @@ def get_version(): Deprecated since 1.8.0. Will be removed in 1.9.0. + Returns: + tuple: + * name of compiler (str): mscv + * compiler version (str): msvccompiler.get_build_version() """ warnings.warn( "native_compiler.get_version is deprecated.\n", @@ -296,6 +300,8 @@ def get_gccxml_compiler(): Deprecated since 1.8.0. Will be removed in 1.9.0. + Returns: + str: mscvXX, where XX is a version number. Works only on windows. """ warnings.warn( "native_compiler.get_gccxml_compiler is deprecated.\n", @@ -311,15 +317,16 @@ def get_gccxml_compiler(): def get_tr1(name): - """ - When using libstd++, there is a tr1 namespace. - - Note that tr1 was also replaced by std in declarations.py, - for the parent attribute. + """In libstd++ the tr1 namespace needs special care. Return either an empty string or tr1::, useful for appending to search patterns. + Args: + name (str): the name of the declaration + + Returns: + str: an empty string or "tr1::" """ tr1 = "" if "tr1" in name: From 9caee0f8e7319630203afc92fa01f9c962b6fd34 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 28 Apr 2016 23:34:17 +0200 Subject: [PATCH 122/268] Use sphinx.ext.napoleon, which is the extension shipped with sphinx --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index f6c19689..e903aad4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -31,7 +31,7 @@ # ones. extensions = [ 'sphinx.ext.autodoc', - 'sphinxcontrib.napoleon' + 'sphinx.ext.napoleon' ] # Add any paths that contain templates here, relative to this directory. From d22268246195a1f59fc7eaedd66a98320adb0f88 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 28 Apr 2016 23:49:12 +0200 Subject: [PATCH 123/268] Update and cleanup legacy update issue doc (#51) - Use a real arrow - Add a comment about this page being there only for historical reasons - Add some text to better separate the examples in the list - Move the page at the end of the doc for release 1.8.0 --- docs/index.rst | 2 +- docs/upgrade_issues.rst | 25 +++++++++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 986c7e50..871a31a2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -54,12 +54,12 @@ Documentation contents documentation query_interface design - upgrade_issues users links releasing history apidocs/api + upgrade_issues .. _`Boost Software License`: http://boost.org/more/license_info.html .. _`Travis`: https://travis-ci.org/gccxml/pygccxml/builds diff --git a/docs/upgrade_issues.rst b/docs/upgrade_issues.rst index 93c41b36..5489d762 100644 --- a/docs/upgrade_issues.rst +++ b/docs/upgrade_issues.rst @@ -1,11 +1,15 @@ -================================= -GCC-XML 0.7 -> 0.9 upgrade issues -================================= +========================================= +GCC-XML 0.7 → 0.9 upgrade issues (Legacy) +========================================= ------------ Introduction ------------ +This page is kept here for historical reasons. CastXML is the recommended +xml generator and GCC-XML is being phased out. This page will be removed +in version 2.0.0 of pygcxml. + Recently, GCC-XML internal parser was updated to GCC 4.2. The internal representation of source code, provided by GCC's parser, has changed a lot and few backward compatibility issues were introduced. In this document, I will try to cover all @@ -96,7 +100,8 @@ Free and member function default arguments Both versions of GCC-XML have a few issues, related to default arguments. GCC-XML 0.9 fixes some issues, but introduces another ones. Take a look on the following examples: -* +* Example 1 + .. code-block:: c++ void fix_numeric( ull arg=(ull)-1 ); @@ -114,7 +119,8 @@ fixes some issues, but introduces another ones. Take a look on the following exa -* +* Example 2 + .. code-block:: c++ void fix_function_call( int i=calc( 1,2,3) ); @@ -132,7 +138,8 @@ fixes some issues, but introduces another ones. Take a look on the following exa -* +* Example 3 + .. code-block:: c++ void typedef__func( const typedef_::alias& position = typedef_::alias() ); @@ -150,7 +157,8 @@ fixes some issues, but introduces another ones. Take a look on the following exa -* +* Example 4 + .. code-block:: c++ void typedef__func2( const typedef_::alias& position = alias() ); @@ -169,7 +177,8 @@ fixes some issues, but introduces another ones. Take a look on the following exa -* +* Example 5 + .. code-block:: c++ node* clone_tree( const std::vector &types=std::vector() ); From 16c881d78313cb7f5abe62f83616ec52ac765a24 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 1 May 2016 00:02:28 +0200 Subject: [PATCH 124/268] Deprecate the enum class in utils This is not used in pygccxml; but also not by py++ To reduce the maintenance burden; unused methods/classes are being dropped. If somebody needs this class, the solution is to copy and implement it in their own code --- pygccxml/utils/utils.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index 3318bde6..c39c0a5d 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -238,6 +238,10 @@ def reset(self): class enum(object): """ + A small enum object. + + Deprecated since 1.8.0. Will be removed in 1.9.0. + Usage example: .. code-block:: python @@ -251,8 +255,25 @@ class fruits(enum): """ + def __init__(self): + super(enum, self).__init__() + warnings.warn("enum is deprecated.", DeprecationWarning) + @classmethod def has_value(cls, enum_numeric_value): + """ + Check if the enum contains the value. + + Deprecated since 1.8.0. Will be removed in 1.9.0. + + Args: + enum_numeric_value (int): the value to search for + + Returns: + boolean: True or False + + """ + warnings.warn("enum.has_value is deprecated.", DeprecationWarning) for name, value in cls.__dict__.items(): if enum_numeric_value == value: return True @@ -261,6 +282,19 @@ def has_value(cls, enum_numeric_value): @classmethod def name_of(cls, enum_numeric_value): + """ + Name of the value. + + Deprecated since 1.8.0. Will be removed in 1.9.0. + + Args: + enum_numeric_value (int): the value to search for + + Returns: + str: the name of the value + + """ + warnings.warn("enum.name_of is deprecated.", DeprecationWarning) for name, value in cls.__dict__.items(): if enum_numeric_value == value: return name From 7d72ba62383cf76b6dc98b1210f627f36f195b3c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 1 May 2016 00:21:38 +0200 Subject: [PATCH 125/268] Add types to docstring --- pygccxml/utils/utils.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index c39c0a5d..a4e4c392 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -18,6 +18,12 @@ def is_str(string): """ Python 2 and 3 compatible string checker. + Args: + string (str | basestring): the string to check + + Returns: + bool: True or False + """ if sys.version_info >= (3, 0): return isinstance(string, str) @@ -270,7 +276,7 @@ def has_value(cls, enum_numeric_value): enum_numeric_value (int): the value to search for Returns: - boolean: True or False + bool: True or False """ warnings.warn("enum.has_value is deprecated.", DeprecationWarning) From 82c8da834593af878961a2fe055382e901912acd Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Sun, 1 May 2016 15:44:19 -0600 Subject: [PATCH 126/268] Fix errors in -std=c++11 mode `free_operators.hpp` had a couple of instances of narrowing conversions within braced initializers, which is ill-formed since C++11. `type_traits.hpp` had two instances of aggregates being value-initialized using empty parentheses. Since these aggregates had implicitly deleted default constructors (due to the presence of `const` data members), value-initialization performs default-initialization, which is ill-formed. We need aggregate-initialization to be performed, so the initialization must use braces instead of parentheses for C++11 and later. Change-Id: Ie4d0365fed7fcccf18dfb2c0b341a3bb34abe645 --- unittests/data/free_operators.hpp | 4 ++-- unittests/data/type_traits.hpp | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/unittests/data/free_operators.hpp b/unittests/data/free_operators.hpp index 961a2e01..ee1f5450 100644 --- a/unittests/data/free_operators.hpp +++ b/unittests/data/free_operators.hpp @@ -32,12 +32,12 @@ bool operator!( const number& x ){ } number operator*( const number& n, double i ){ - number n2 = { n.i * i }; + number n2 = { static_cast(n.i * i) }; return n2; } number operator*( double i, const number& n ){ - number n2 = { n.i * i }; + number n2 = { static_cast(n.i * i) }; return n2; } diff --git a/unittests/data/type_traits.hpp b/unittests/data/type_traits.hpp index 7991a57c..08254ee8 100644 --- a/unittests/data/type_traits.hpp +++ b/unittests/data/type_traits.hpp @@ -576,12 +576,19 @@ namespace has_trivial_constructor{ namespace details{ struct const_item{ const int values[10]; }; - - void test_const_item( const_item x = const_item() ); - struct const_container{ const const_item items[10]; }; +#if __cplusplus >= 201103L + // C++11 and later must use braces to trigger aggregate initialization. + // Using parentheses will cause value-initialization, and since the + // two classes above have implicitly deleted default constructors, + // that causes default initialization to be performed, which is ill-formed. + void test_const_item( const_item x = const_item{} ); + void test_const_container( const_container x = const_container{} ); +#else + void test_const_item( const_item x = const_item() ); void test_const_container( const_container x = const_container() ); +#endif } From cd337cb4f400fd8084853a12f92ee45fa8cb8d21 Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Sun, 1 May 2016 14:48:43 -0600 Subject: [PATCH 127/268] Pipe `stderr` when calling `subprocess.Popen` Code that uses the `which` command to find *castxml* and *clang++* now pipes `stderr` in addition to `stdout`. This prevents error messages from being printed if the executables being searched for are not on `PATH`. Change-Id: Ic28382c67364bd08f137aa37abde07618ca932e1 --- pygccxml/parser/config.py | 4 +++- pygccxml/utils/utils.py | 12 +++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index d46eae0f..2331aa91 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -431,9 +431,11 @@ def create_compiler_path(xml_generator, compiler_path): if platform.system() != 'Windows': # On windows there is no need for the compiler path p = subprocess.Popen( - ['which', 'clang++'], stdout=subprocess.PIPE) + ['which', 'clang++'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) compiler_path = p.stdout.read().decode("utf-8").rstrip() p.stdout.close() + p.stderr.close() # No clang found; use gcc if compiler_path == '': compiler_path = '/usr/bin/c++' diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index a4e4c392..8c1da88c 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -50,18 +50,24 @@ def find_xml_generator(name=None): if name is None: name = "castxml" - p = subprocess.Popen([command, name], stdout=subprocess.PIPE) + p = subprocess.Popen([command, name], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) path = p.stdout.read().decode("utf-8") p.stdout.close() + p.stderr.close() if path == "": name = "gccxml" - p = subprocess.Popen([command, name], stdout=subprocess.PIPE) + p = subprocess.Popen([command, name], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) path = p.stdout.read().decode("utf-8") p.stdout.close() + p.stderr.close() else: - p = subprocess.Popen([command, name], stdout=subprocess.PIPE) + p = subprocess.Popen([command, name], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) path = p.stdout.read().decode("utf-8") p.stdout.close() + p.stderr.close() if path == "": raise(Exception( "No c++ parser found. Please install castxml or gccxml.")) From 74c2e34beba3e4877bab5eee0b8d9218bb1d7fd6 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 2 May 2016 23:26:08 +0200 Subject: [PATCH 128/268] Fix badge urls on develop (see also #50) --- README.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 95048145..4d3955e9 100644 --- a/README.rst +++ b/README.rst @@ -1,17 +1,17 @@ pygccxml ======== -.. image:: https://travis-ci.org/gccxml/pygccxml.svg?branch=master +.. image:: https://travis-ci.org/gccxml/pygccxml.svg?branch=develop :target: https://travis-ci.org/gccxml/pygccxml :alt: Unit tests status -.. image:: https://coveralls.io/repos/gccxml/pygccxml/badge.svg?branch=master - :target: https://coveralls.io/r/gccxml/pygccxml?branch=master +.. image:: https://coveralls.io/repos/gccxml/pygccxml/badge.svg?branch=develop + :target: https://coveralls.io/r/gccxml/pygccxml?branch=develop :alt: Code coverage status -.. image:: https://readthedocs.io/projects/pygccxml/badge/?version=master - :target: https://readthedocs.io/projects/pygccxml/?badge=master +.. image:: https://readthedocs.org/projects/pygccxml/badge/?version=develop + :target: http://pygccxml.readthedocs.io/en/develop/?badge=develop :alt: Documentation status -.. image:: https://www.quantifiedcode.com/api/v1/project/117af14ef32a455fb7b3762e21083fb3/snapshot/origin:master:HEAD/badge.svg - :target: https://www.quantifiedcode.com/app/project/117af14ef32a455fb7b3762e21083fb3?branch=origin%2Fmaster&tab=basics +.. image:: https://www.quantifiedcode.com/api/v1/project/117af14ef32a455fb7b3762e21083fb3/snapshot/origin:develop:HEAD/badge.svg + :target: https://www.quantifiedcode.com/app/project/117af14ef32a455fb7b3762e21083fb3?branch=origin%2Fdevelop&tab=basics :alt: Code quality status pygccxml is a specialized XML reader that reads the output from CastXML or GCCXML. It provides a simple framework to navigate C++ declarations, using Python classes. From 882625f9535f937fcf4e52e3d5995c260184fdfa Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 2 May 2016 23:38:14 +0200 Subject: [PATCH 129/268] Add .gitattributes to prevent overwriting of the Readme file when merging hotfix branches to develop From: http://www.alberts.me/post/always-keep-your-copy-of-a-particular-file-in-a-git-merge/ git config merge.ours.name '"always keep ours" merge driver' git config merge.ours.driver 'touch %A' echo "README.rst merge=ours" >> .gitattributes git add .gitattributes git commit -m "keep my copy of the README.rst file" --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..66755390 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +README.rst merge=ours From 3b035465da1088550bd20a4c6d4a908d9591ecc5 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 7 May 2016 12:45:28 +0200 Subject: [PATCH 130/268] Remove unused imports --- pygccxml/declarations/declaration.py | 1 - pygccxml/declarations/function_traits.py | 1 - pygccxml/parser/config.py | 1 - unittests/declaration_matcher_tester.py | 1 - unittests/test_cpp_standards.py | 1 - unittests/test_map_gcc5.py | 1 - unittests/test_utils.py | 1 - unittests/test_va_list_tag_removal.py | 1 - 8 files changed, 8 deletions(-) diff --git a/pygccxml/declarations/declaration.py b/pygccxml/declarations/declaration.py index 249c20b3..65adb136 100644 --- a/pygccxml/declarations/declaration.py +++ b/pygccxml/declarations/declaration.py @@ -9,7 +9,6 @@ """ -import warnings from . import algorithm from . import algorithms_cache from .. import utils diff --git a/pygccxml/declarations/function_traits.py b/pygccxml/declarations/function_traits.py index 3305b2cf..15629f6a 100644 --- a/pygccxml/declarations/function_traits.py +++ b/pygccxml/declarations/function_traits.py @@ -9,7 +9,6 @@ from . import calldef from . import type_traits -from . import class_declaration def is_same_return_type(f1, f2): diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index d46eae0f..c49f4250 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -12,7 +12,6 @@ import copy import platform import subprocess -import warnings from .. import utils diff --git a/unittests/declaration_matcher_tester.py b/unittests/declaration_matcher_tester.py index ab991111..818f0ec0 100644 --- a/unittests/declaration_matcher_tester.py +++ b/unittests/declaration_matcher_tester.py @@ -8,7 +8,6 @@ from pygccxml import parser from pygccxml import declarations -from pygccxml import utils class tester_t(parser_test_case.parser_test_case_t): diff --git a/unittests/test_cpp_standards.py b/unittests/test_cpp_standards.py index f5ccb413..53e5f1f3 100644 --- a/unittests/test_cpp_standards.py +++ b/unittests/test_cpp_standards.py @@ -6,7 +6,6 @@ import parser_test_case from pygccxml import parser -from pygccxml import utils class Test(parser_test_case.parser_test_case_t): diff --git a/unittests/test_map_gcc5.py b/unittests/test_map_gcc5.py index 35dfe44d..602ac841 100644 --- a/unittests/test_map_gcc5.py +++ b/unittests/test_map_gcc5.py @@ -6,7 +6,6 @@ import parser_test_case from pygccxml import parser -from pygccxml import utils from pygccxml import declarations diff --git a/unittests/test_utils.py b/unittests/test_utils.py index 6117b79f..3b6809df 100644 --- a/unittests/test_utils.py +++ b/unittests/test_utils.py @@ -4,7 +4,6 @@ import os import unittest -import autoconfig import parser_test_case from pygccxml import utils diff --git a/unittests/test_va_list_tag_removal.py b/unittests/test_va_list_tag_removal.py index c4014188..517d224d 100644 --- a/unittests/test_va_list_tag_removal.py +++ b/unittests/test_va_list_tag_removal.py @@ -9,7 +9,6 @@ from pygccxml import parser from pygccxml import declarations -from pygccxml import utils class tester_t(parser_test_case.parser_test_case_t): From 7273ee0b4e04f7372713c5407fafe28ebcc6d269 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 8 May 2016 14:04:39 +0200 Subject: [PATCH 131/268] Add c++11 and c++03 testing with gcc4.8.2 The c++11 test is allowed to fail as some changes to the code / tests need to be done to make it work. --- .travis.yml | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0de575b9..fc2ea930 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,13 +37,29 @@ matrix: sources: - ubuntu-toolchain-r-test packages: - # This will be gcc 5.2.1 + # gcc 5.2.1 - g++-5 - os: linux dist: trusty sudo: required python: 3.5 env: XML_GENERATOR="castxml" + - os: linux + dist: trusty + sudo: required + python: 3.5 + env: + # gcc 4.8.2 with c++03 + - XML_GENERATOR="castxml" + - CPPSTD="-std=c++03" + - os: linux + dist: trusty + sudo: required + python: 3.5 + env: + # gcc 4.8.2 with c++11 + - XML_GENERATOR="castxml" + - CPPSTD="-std=c++11" - os: linux dist: trusty sudo: required @@ -56,7 +72,7 @@ matrix: sources: - ubuntu-toolchain-r-test packages: - # This will be gcc 5.3.0 + # gcc 5.3.0 - g++-5 - os: osx osx_image: xcode7.2 @@ -70,6 +86,11 @@ matrix: env: - XML_GENERATOR="castxml" - TRAVIS_PYTHON_VERSION="3" + allow_failures: + - env: + - XML_GENERATOR="castxml" + - CPPSTD="-std=c++11" + python: 3.5 before_install: @@ -102,6 +123,16 @@ before_install: - if [[ "$XML_GENERATOR" == "gccxml" ]]; then sudo apt-get update -qq; fi - if [[ "$XML_GENERATOR" == "gccxml" ]]; then sudo apt-get install -qq gccxml; fi + # Patch the c++ version to test on the fly + - if [[ $CPPSTD == "-std=c++03" ]]; then + cd unittests && sed -i s%compiler=None,%compiler=None,\\n\ \ \ \ \ \ \ \ cflags=\"-std=c++03\",%g autoconfig.py && cd ..; + fi + + # Patch the c++ version to test on the fly + - if [[ $CPPSTD == "-std=c++11" ]]; then + cd unittests && sed -i s%compiler=None,%compiler=None,\\n\ \ \ \ \ \ \ \ cflags=\"-std=c++11\",%g autoconfig.py && cd ..; + fi + # Patch the compiler path on the fly for gcc5 testing - if [[ "$COMPILER" == "g++-5" ]] && [[ $XML_GENERATOR == "castxml" ]]; then cd unittests && sed -i s%compiler=None%compiler=\"/usr/bin/g++-5\"%g autoconfig.py && cd ..; From d9b613eec6cbcfffc38b559f44a7e4072de8a992 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 9 May 2016 23:30:17 +0200 Subject: [PATCH 132/268] The c++11 test is green now, remove allow_failures (#53) --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index fc2ea930..e49cf88b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -86,11 +86,6 @@ matrix: env: - XML_GENERATOR="castxml" - TRAVIS_PYTHON_VERSION="3" - allow_failures: - - env: - - XML_GENERATOR="castxml" - - CPPSTD="-std=c++11" - python: 3.5 before_install: From 6768962e05ee4ceae183b151a177911570b6fed7 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 9 May 2016 23:33:42 +0200 Subject: [PATCH 133/268] Use the latest version of castxml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e49cf88b..544b6843 100644 --- a/.travis.yml +++ b/.travis.yml @@ -99,13 +99,13 @@ before_install: # Download castxml binaries - if [ "$TRAVIS_OS_NAME" = "osx" ]; then if [ ! -e ${HOME}/castxml ]; then - curl https://midas3.kitware.com/midas/download/item/318762/castxml-macosx.tar.gz | tar zxf - -C ${HOME}; + curl https://midas3.kitware.com/midas/download/item/460403/castxml-macosx.tar.gz | tar zxf - -C ${HOME}; fi; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]] && [[ $XML_GENERATOR == "castxml" ]]; then if [ ! -e ${HOME}/castxml ]; then - wget -O - https://midas3.kitware.com/midas/download/item/318227/castxml-linux.tar.gz | tar zxf - -C ${HOME}; + wget -O - https://midas3.kitware.com/midas/download/item/460468/castxml-linux.tar.gz | tar zxf - -C ${HOME}; fi; fi From 3d1e20db645cdfc1a76690bdbced410efa16972e Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 10 May 2016 00:17:15 +0200 Subject: [PATCH 134/268] The castxml urls have changed with the newest version --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 544b6843..673e1bc2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -99,13 +99,13 @@ before_install: # Download castxml binaries - if [ "$TRAVIS_OS_NAME" = "osx" ]; then if [ ! -e ${HOME}/castxml ]; then - curl https://midas3.kitware.com/midas/download/item/460403/castxml-macosx.tar.gz | tar zxf - -C ${HOME}; + curl http://midas3.kitware.com/midas/download/bitstream/460403/castxml-macosx.tar.gz | tar zxf - -C ${HOME}; fi; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]] && [[ $XML_GENERATOR == "castxml" ]]; then if [ ! -e ${HOME}/castxml ]; then - wget -O - https://midas3.kitware.com/midas/download/item/460468/castxml-linux.tar.gz | tar zxf - -C ${HOME}; + wget -O - https://midas3.kitware.com/midas/download/bitstream/460468/castxml-linux.tar.gz | tar zxf - -C ${HOME}; fi; fi From 71f6bdea8c4278d29f63aa7e442a5d846e810a51 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 10 May 2016 22:08:04 +0200 Subject: [PATCH 135/268] Update the castxml OS X binary URL The URL was correct, but the download failed due to the http to https redirect. Also, use wget like for the Linux binary --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 673e1bc2..34d46ae9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -99,7 +99,7 @@ before_install: # Download castxml binaries - if [ "$TRAVIS_OS_NAME" = "osx" ]; then if [ ! -e ${HOME}/castxml ]; then - curl http://midas3.kitware.com/midas/download/bitstream/460403/castxml-macosx.tar.gz | tar zxf - -C ${HOME}; + wget -O - https://midas3.kitware.com/midas/download/bitstream/460403/castxml-macosx.tar.gz | tar zxf - -C ${HOME}; fi; fi From 5cdd853304bf4eb67c18cb8c9a25b6a245fa3915 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 10 May 2016 23:30:33 +0200 Subject: [PATCH 136/268] Add c++14 travis build with gcc 5.3.0 --- .travis.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.travis.yml b/.travis.yml index 34d46ae9..a2d321f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -74,6 +74,21 @@ matrix: packages: # gcc 5.3.0 - g++-5 + - os: linux + dist: trusty + sudo: required + python: 3.5 + env: + - XML_GENERATOR="castxml" + - COMPILER=g++-5 + - CPPSTD="-std=c++14" + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + # gcc 5.3.0 + - g++-5 - os: osx osx_image: xcode7.2 language: generic @@ -128,6 +143,11 @@ before_install: cd unittests && sed -i s%compiler=None,%compiler=None,\\n\ \ \ \ \ \ \ \ cflags=\"-std=c++11\",%g autoconfig.py && cd ..; fi + # Patch the c++ version to test on the fly + - if [[ $CPPSTD == "-std=c++14" ]]; then + cd unittests && sed -i s%compiler=None,%compiler=None,\\n\ \ \ \ \ \ \ \ cflags=\"-std=c++14\",%g autoconfig.py && cd ..; + fi + # Patch the compiler path on the fly for gcc5 testing - if [[ "$COMPILER" == "g++-5" ]] && [[ $XML_GENERATOR == "castxml" ]]; then cd unittests && sed -i s%compiler=None%compiler=\"/usr/bin/g++-5\"%g autoconfig.py && cd ..; From 44d35d7251195cfc3d6bb6490ec254fdf8429b63 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 May 2016 19:35:10 +0200 Subject: [PATCH 137/268] Run examples in a wrapped environment to pick up the right pygccxml --- unittests/example_tester.py | 10 ++++++--- unittests/example_tester_wrap.py | 35 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 unittests/example_tester_wrap.py diff --git a/unittests/example_tester.py b/unittests/example_tester.py index c494580f..b5478810 100644 --- a/unittests/example_tester.py +++ b/unittests/example_tester.py @@ -1,3 +1,6 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt import os import fnmatch @@ -18,16 +21,17 @@ def test_example(self): # Allows to cover files run in a subprocess # http://nedbatchelder.com/code/coverage/subprocess.html env["COVERAGE_PROCESS_START"] = path + "/../.coveragerc" - path += "/../docs/examples" # Find all the examples files file_paths = [] - for root, dirnames, filenames in os.walk(path): + for root, dirnames, filenames in os.walk(path + "/../docs/examples"): for file_path in fnmatch.filter(filenames, '*.py'): file_paths.append(os.path.join(root, file_path)) for file_path in file_paths: - return_code = subprocess.call(["python", file_path], env=env) + return_code = subprocess.call( + ["python", path + "/example_tester_wrap.py", file_path], + env=env) self.assertFalse( return_code, msg="The example %s did not run correctly" % file_path) diff --git a/unittests/example_tester_wrap.py b/unittests/example_tester_wrap.py new file mode 100644 index 00000000..dbd27bfc --- /dev/null +++ b/unittests/example_tester_wrap.py @@ -0,0 +1,35 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +import os +import sys + +# This wrapper layer allows to execute the examples for the unittests +# in a separate environment, where the sys.path has been hacked to point +# to the pygccxml source tree (we do not want to pickup any pygccxml installed +# on the system). Unfortunately passing the PYTHONPATH as env variable to +# subprocess just appends to the sys.path ... here we want to insert at +# position 1 so that the right pygccxml is found + + +example_file = sys.argv[1] +example_folder = os.path.dirname(example_file) +root = os.path.normpath( + os.path.dirname(sys.modules[__name__].__file__) + "/../") + +# Add the root folder to the path, so that the examples are not run against +# whatever pygccxml version is installed +sys.path.insert(1, root) + +# Hack the __file__ location, so that the example thinks it is in the +# docs/examples folder +sys.modules[__name__].__file__ = example_file + +# Run the example +if sys.version_info >= (3, 0): + with open(example_file) as f: + code = compile(f.read(), example_file, "exec") + exec(code, None, None) +else: + execfile(example_file) From f751825e18963523740d99c610bd4418a95c454a Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Fri, 29 Apr 2016 17:05:17 -0600 Subject: [PATCH 138/268] Fix patching of enums in default arguments for C++03 Given the following code namespace ns { enum color {red, green, blue}; void test( color arg=blue ); } CastXML produces a fully qualified name for the default argument - `::ns::color::blue`. While this default argument string is valid for C++11 and later, and indeed required if `color` were a scoped enumeration, the default argument is invalid for C++03 code. Prior to C++11, enumerator names were added to the enclosing scope, so they could not be qualified using the enum-name. Hence, for C++03, the default argument needs to be patched to say `::ns::blue`. Change-Id: I72c5d4fc53c5b5dc6f5fa38d10cb5484ba3bf85a --- pygccxml/parser/patcher.py | 29 ++++++---- pygccxml/parser/source_reader.py | 34 ++++-------- pygccxml/utils/__init__.py | 1 + pygccxml/utils/utils.py | 91 ++++++++++++++++++++++++++++++++ unittests/data/patcher.hpp | 23 ++++++++ unittests/patcher_tester.py | 49 ++++++++++------- 6 files changed, 175 insertions(+), 52 deletions(-) diff --git a/pygccxml/parser/patcher.py b/pygccxml/parser/patcher.py index c39865c5..489dc8db 100644 --- a/pygccxml/parser/patcher.py +++ b/pygccxml/parser/patcher.py @@ -10,9 +10,10 @@ class default_argument_patcher_t(object): - def __init__(self, enums): + def __init__(self, enums, cxx_std): object.__init__(self) self.__enums = enums + self.__cxx_std = cxx_std def __call__(self, decl): for arg in decl.arguments: @@ -54,8 +55,12 @@ def __is_unqualified_enum(self, func, arg): def __fix_unqualified_enum(self, func, arg): type_ = declarations.remove_reference(declarations.remove_cv(arg.type)) enum_type = declarations.enum_declaration(type_) + if self.__cxx_std.is_cxx11_or_greater: + qualifier_decl_string = enum_type.decl_string + else: + qualifier_decl_string = enum_type.parent.decl_string return self.__join_names( - enum_type.parent.decl_string, + qualifier_decl_string, arg.default_value.split('::')[-1]) def __is_invalid_integral(self, func, arg): @@ -95,19 +100,25 @@ def __fix_invalid_integral(self, func, arg): pass # may be we deal with enum + # CastXML qualifies the enum value with enum type, so split the + # argument and use only the enum value + enum_value = arg.default_value.split('::')[-1] parent = func.parent while parent: - found = self.__find_enum(parent, arg.default_value) + found = self.__find_enum(parent, enum_value) if found: if declarations.is_fundamental(arg.type) and ' ' in \ arg.type.decl_string: template = '(%s)(%s)' else: template = '%s(%s)' + if self.__cxx_std.is_cxx11_or_greater: + qualifier_decl_string = found.decl_string + else: + qualifier_decl_string = found.parent.decl_string return template % (arg.type.decl_string, - self.__join_names( - found.parent.decl_string, - arg.default_value)) + self.__join_names(qualifier_decl_string, + enum_value)) else: parent = parent.parent @@ -133,7 +144,7 @@ def __fix_invalid_integral(self, func, arg): def __find_enum(self, scope, default_value): # this algorithm could be improved: it could take into account - # 1. unnamed namespaced + # 1. unnamed namespace # 2. location within files for enum in self.__enums: @@ -222,8 +233,8 @@ def __call__(self, decl): _casting_oper_patcher_ = casting_operator_patcher_t() -def fix_calldef_decls(decls, enums): - default_arg_patcher = default_argument_patcher_t(enums) +def fix_calldef_decls(decls, enums, cxx_std): + default_arg_patcher = default_argument_patcher_t(enums, cxx_std) # decls should be flat list of all declarations, you want to apply patch on for decl in decls: default_arg_patcher(decl) diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index db4eb950..8f9c080f 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -89,6 +89,7 @@ def __init__(self, config, cache=None, decl_factory=None, join_decls=True): self.__join_decls = join_decls self.__search_directories = [] self.__config = config + self.__cxx_std = utils.cxx_standard(config.cflags) self.__search_directories.append(config.working_directory) self.__search_directories.extend(config.include_paths) if not cache: @@ -159,30 +160,12 @@ def __create_command_line_castxml(self, source_file, xmlfile): # On mac or linux, use gcc or clang (the flag is the same) cmd.append('--castxml-cc-gnu ') - # Check for -std=xx flags passed to the compiler. - # A regex could be used but this is a moving target. - # See c++1z for example. It is preferable to have a defined - # list of what is allowed. http://clang.llvm.org/cxx_status.html - # - # Version 98 and 03 are only there in the case somebody is using - # these flags; this is the equivalent to not passing these flags. - standards = [ - "-std=c++98", - "-std=c++03", - "-std=c++11", - "-std=c++14", - "-std=c++1z"] - - std_flag = "" - for standard in standards: - if standard in self.__config.cflags: - std_flag = " " + standard + " " - - # A -std= flag was passed, but is not in the list - if "-std=" in self.__config.cflags and std_flag == "": - raise(RuntimeError("Unknown -std=c++xx flag used !")) - - if std_flag != "": + if self.__cxx_std.is_implicit: + std_flag = '' + else: + std_flag = ' ' + self.__cxx_std.stdcxx + ' ' + + if std_flag: cmd.append( '"(" ' + self.__config.compiler_path + std_flag + '")"') else: @@ -492,7 +475,8 @@ def __parse_xml_file(self, xml_file): # void ddd(){ typedef typename X::Y YY;} # if I will fail on this bug next time, the right way to fix it may be # different - patcher.fix_calldef_decls(scanner_.calldefs(), scanner_.enums()) + patcher.fix_calldef_decls(scanner_.calldefs(), scanner_.enums(), + self.__cxx_std) decls = [ inst for inst in iter( decls.values()) if isinstance( diff --git a/pygccxml/utils/__init__.py b/pygccxml/utils/__init__.py index 92bf0f72..fe76c6a6 100644 --- a/pygccxml/utils/__init__.py +++ b/pygccxml/utils/__init__.py @@ -17,6 +17,7 @@ from .utils import normalize_path from .utils import find_xml_generator from .utils import get_tr1 +from .utils import cxx_standard # Version of xml generator which was used. xml_generator = None diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index 8c1da88c..a0792d24 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -378,3 +378,94 @@ def get_tr1(name): if "tr1" in name: tr1 = "tr1::" return tr1 + + +class cxx_standard(object): + """Helper class for parsing the C++ standard version. + + This class holds the C++ standard version the XML generator has been + configured with, and provides helpers functions for querying C++ standard + version related information. + """ + + __STD_CXX = { + '-std=c++98': 199711, + '-std=gnu++98': 199711, + '-std=c++03': 199711, + '-std=gnu++03': 199711, + '-std=c++0x': 201103, + '-std=gnu++0x': 201103, + '-std=c++11': 201103, + '-std=gnu++11': 201103, + '-std=c++1y': 201402, + '-std=gnu++1y': 201402, + '-std=c++14': 201402, + '-std=gnu++14': 201402, + '-std=c++1z': float('inf'), + '-std=gnu++1z': float('inf'), + } + + def __init__(self, cflags): + """Class constructor that parses the XML generator's command line + + Args: + cflags (str): cflags command line arguments passed to the XML + generator + """ + super(cxx_standard, self).__init__() + + self._stdcxx = None + self._is_implicit = False + for key in cxx_standard.__STD_CXX: + if key in cflags: + self._stdcxx = key + self._cplusplus = cxx_standard.__STD_CXX[key] + + if not self._stdcxx: + if '-std=' in cflags: + raise RuntimeError('Unknown -std=c++xx flag used') + + # Assume c++03 by default + self._stdcxx = '-std=c++03' + self._cplusplus = cxx_standard.__STD_CXX['-std=c++03'] + self._is_implicit = True + + @property + def stdcxx(self): + """Returns the -std=c++xx option passed to the constructor""" + return self._stdcxx + + @property + def is_implicit(self): + """Indicates whether a -std=c++xx was specified""" + return self._is_implicit + + @property + def is_cxx03(self): + """Returns true if -std=c++03 is being used""" + return self._cplusplus == cxx_standard.__STD_CXX['-std=c++03'] + + @property + def is_cxx11(self): + """Returns true if -std=c++11 is being used""" + return self._cplusplus == cxx_standard.__STD_CXX['-std=c++11'] + + @property + def is_cxx11_or_greater(self): + """Returns true if -std=c++11 or a newer standard is being used""" + return self._cplusplus >= cxx_standard.__STD_CXX['-std=c++11'] + + @property + def is_cxx14(self): + """Returns true if -std=c++14 is being used""" + return self._cplusplus == cxx_standard.__STD_CXX['-std=c++14'] + + @property + def is_cxx14_or_greater(self): + """Returns true if -std=c++14 or a newer standard is being used""" + return self._cplusplus >= cxx_standard.__STD_CXX['-std=c++14'] + + @property + def is_cxx1z(self): + """Returns true if -std=c++1z is being used""" + return self._cplusplus == cxx_standard.__STD_CXX['-std=c++1z'] diff --git a/unittests/data/patcher.hpp b/unittests/data/patcher.hpp index cae233fb..086c0bdb 100644 --- a/unittests/data/patcher.hpp +++ b/unittests/data/patcher.hpp @@ -25,6 +25,22 @@ void fix_enum3( fruit arg=orange ); } +#if __cplusplus >= 201103L +namespace ns4{ + +enum class color {red, green, blue}; +void fix_enum4( color arg=color::blue ); + +} + +namespace ns5{ + +using namespace ns4; +void fix_enum5( color arg=color::blue ); + +} +#endif + typedef unsigned long long ull; void fix_numeric( ull arg=(ull)-1 ); @@ -76,6 +92,13 @@ static int const DEFAULT_1 = 20; int fun2( int arg1=DEFAULT_1, int arg2=ns1::DEFAULT_1, long arg3=::ns1::st1::DEFAULT_2 ); +enum ACE_Log_Priority_Index +{ + LM_INVALID_BIT_INDEX = 32 +}; +static int log_priority_enabled(long priority_index = LM_INVALID_BIT_INDEX); + + /*struct default_arg_t{};*/ /*default_arg_t create_default_argument();*/ /*void double_call( default_arg_t x=create_default_argument() );*/ diff --git a/unittests/patcher_tester.py b/unittests/patcher_tester.py index 297777d1..66983a33 100644 --- a/unittests/patcher_tester.py +++ b/unittests/patcher_tester.py @@ -19,29 +19,50 @@ def __init__(self, architecture, *args): parser_test_case.parser_test_case_t.__init__(self, *args) self.architecture = architecture self.global_ns = None + self.__cxx_std = utils.cxx_standard(self.config.cflags) def test_enum_patcher(self): fix_enum = self.global_ns.free_fun("fix_enum") default_val = fix_enum.arguments[0].default_value - self.assertEqual(default_val, "::ns1::ns2::apple") + if self.__cxx_std.is_cxx11_or_greater: + val = "::ns1::ns2::fruit::apple" + else: + val = "::ns1::ns2::apple" + self.assertEqual(default_val, val) if 32 == self.architecture or "CastXML" in utils.xml_generator: fix_enum2 = self.global_ns.free_fun("fix_enum2") default_val = fix_enum2.arguments[0].default_value - self.assertEqual(default_val, "::ns1::ns2::apple") + self.assertEqual(default_val, val) ns1 = self.global_ns.namespace("ns1") ns2 = ns1.namespace("ns2") fix_enum2 = ns2.free_fun("fix_enum2") default_val = fix_enum2.arguments[0].default_value - self.assertEqual(default_val, "::ns1::ns2::apple") + self.assertEqual(default_val, val) fix_enum3 = self.global_ns.free_fun("fix_enum3") default_val = fix_enum3.arguments[0].default_value - self.assertEqual(default_val, "::ns1::ns2::orange") + val = val.replace("apple", "orange") + self.assertEqual(default_val, val) + + if self.__cxx_std.is_cxx11_or_greater: + fix_enum4 = self.global_ns.free_fun("fix_enum4") + default_val = fix_enum4.arguments[0].default_value + self.assertEqual(default_val, "::ns4::color::blue") + + fix_enum5 = self.global_ns.free_fun("fix_enum5") + default_val = fix_enum5.arguments[0].default_value + self.assertEqual(default_val, "::ns4::color::blue") - # double_call = declarations.find_declaration( - # decls, type=declarations.free_function_t, name='double_call' ) + lpe = self.global_ns.free_fun("log_priority_enabled") + default_val = lpe.arguments[0].default_value + if self.__cxx_std.is_cxx11_or_greater: + val = "(long int)" + \ + "(::ACE_Log_Priority_Index::LM_INVALID_BIT_INDEX)" + else: + val = "(long int)(::LM_INVALID_BIT_INDEX)" + self.assertEqual(default_val, val) def test_numeric_patcher(self): fix_numeric = self.global_ns.free_function("fix_numeric") @@ -126,13 +147,8 @@ def test_unqualified_integral_patcher(self): def test_unnamed_enum_patcher(self): fix_unnamed = self.global_ns.free_fun("fix_unnamed") - if ("CastXML" in utils.xml_generator and - utils.xml_output_version >= 1.137): - val = "fx::unnamed" - else: - val = "int(::fx::unnamed)" self.assertEqual( - fix_unnamed.arguments[0].default_value, val) + fix_unnamed.arguments[0].default_value, "int(::fx::unnamed)") def test_function_call_patcher(self): fix_function_call = self.global_ns.free_fun("fix_function_call") @@ -150,9 +166,8 @@ def test_function_call_patcher(self): def test_fundamental_patcher(self): fcall = self.global_ns.free_fun("fix_fundamental") - if ("CastXML" in utils.xml_generator and - utils.xml_output_version >= 1.137): - val = "fundamental::spam::eggs" + if self.__cxx_std.is_cxx11_or_greater: + val = "(unsigned int)(::fundamental::spam::eggs)" else: val = "(unsigned int)(::fundamental::eggs)" self.assertEqual( @@ -163,14 +178,12 @@ def test_constructor_patcher(self): default_val = typedef__func.arguments[0].default_value if "0.9" in utils.xml_generator: val = "typedef_::original_name()" - self.assertEqual(default_val, val) elif "CastXML" in utils.xml_generator: # Most clean output, no need to patch val = "typedef_::alias()" - self.assertEqual(default_val, val) else: val = "::typedef_::alias( )" - self.assertEqual(default_val, val) + self.assertEqual(default_val, val) if 32 == self.architecture: clone_tree = self.global_ns.free_fun("clone_tree") default_values = [] From 2b8de435149397592cc5b92ef63492ad751c4bd2 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 May 2016 22:50:49 +0200 Subject: [PATCH 139/268] Fail on warnings in the examples for the tests The added part of code is not displayed in the documentation and is only useful when run by the tests. --- docs/examples/caching/example.py | 2 ++ docs/examples/caching/example.rst | 2 +- docs/examples/equality/example.py | 2 ++ docs/examples/equality/example.rst | 2 +- docs/examples/parsing-string/example.py | 3 +++ docs/examples/parsing-string/example.rst | 2 +- docs/examples/parsing/example.py | 2 ++ docs/examples/parsing/example.rst | 2 +- docs/examples/searching/example.py | 2 ++ docs/examples/searching/example.rst | 2 +- docs/examples/searching1/example.py | 2 ++ docs/examples/searching1/example.rst | 2 +- docs/examples/variables/example.py | 2 ++ docs/examples/variables/example.rst | 2 +- 14 files changed, 22 insertions(+), 7 deletions(-) diff --git a/docs/examples/caching/example.py b/docs/examples/caching/example.py index 5af86abb..c4fecb27 100644 --- a/docs/examples/caching/example.py +++ b/docs/examples/caching/example.py @@ -8,6 +8,8 @@ import os import sys +import warnings +warnings.simplefilter("error", Warning) # Find out the file location within the sources tree this_module_dir_path = os.path.abspath( os.path.dirname(sys.modules[__name__].__file__)) diff --git a/docs/examples/caching/example.rst b/docs/examples/caching/example.rst index 493b5d13..7e7b677a 100644 --- a/docs/examples/caching/example.rst +++ b/docs/examples/caching/example.rst @@ -16,7 +16,7 @@ To enable caching, you can use the following code: .. literalinclude:: example.py :language: python - :lines: 5,6,7,14-24,26- + :lines: 5,6,7,16-26,28- The first time you run this example, the c++ file will be read and a xml file will be generated: diff --git a/docs/examples/equality/example.py b/docs/examples/equality/example.py index b5be5795..58b1f872 100644 --- a/docs/examples/equality/example.py +++ b/docs/examples/equality/example.py @@ -8,6 +8,8 @@ import os import sys +import warnings +warnings.simplefilter("error", Warning) # Find out the file location within the sources tree this_module_dir_path = os.path.abspath( os.path.dirname(sys.modules[__name__].__file__)) diff --git a/docs/examples/equality/example.rst b/docs/examples/equality/example.rst index f7f150b2..23bf6d84 100644 --- a/docs/examples/equality/example.rst +++ b/docs/examples/equality/example.rst @@ -15,4 +15,4 @@ different ways. Both declarations are then compared. .. literalinclude:: example.py :language: python - :lines: 5,6,7,14-24,26- \ No newline at end of file + :lines: 5,6,7,16-26,28- diff --git a/docs/examples/parsing-string/example.py b/docs/examples/parsing-string/example.py index 8a32c841..cce37e97 100644 --- a/docs/examples/parsing-string/example.py +++ b/docs/examples/parsing-string/example.py @@ -6,6 +6,9 @@ from pygccxml import declarations from pygccxml import parser +import warnings +warnings.simplefilter("error", Warning) + # Find the location of the xml generator (castxml or gccxml) generator_path, generator_name = utils.find_xml_generator() diff --git a/docs/examples/parsing-string/example.rst b/docs/examples/parsing-string/example.rst index 9f3f5f26..28d8eb1e 100644 --- a/docs/examples/parsing-string/example.rst +++ b/docs/examples/parsing-string/example.rst @@ -13,4 +13,4 @@ and how to parse the string containing the c++ code: .. literalinclude:: example.py :language: python - :lines: 5- + :lines: 5,6,7,11- diff --git a/docs/examples/parsing/example.py b/docs/examples/parsing/example.py index dce78ed9..842617e6 100644 --- a/docs/examples/parsing/example.py +++ b/docs/examples/parsing/example.py @@ -8,6 +8,8 @@ import os import sys +import warnings +warnings.simplefilter("error", Warning) # Find out the file location within the sources tree this_module_dir_path = os.path.abspath( os.path.dirname(sys.modules[__name__].__file__)) diff --git a/docs/examples/parsing/example.rst b/docs/examples/parsing/example.rst index 01c7ca4a..5b9d593b 100644 --- a/docs/examples/parsing/example.rst +++ b/docs/examples/parsing/example.rst @@ -17,4 +17,4 @@ and how to parse the c++ file: .. literalinclude:: example.py :language: python - :lines: 5,6,7,14-24,26- + :lines: 5,6,7,16-26,28- diff --git a/docs/examples/searching/example.py b/docs/examples/searching/example.py index bfcb20a3..1ef7b35d 100644 --- a/docs/examples/searching/example.py +++ b/docs/examples/searching/example.py @@ -8,6 +8,8 @@ import os import sys +import warnings +warnings.simplefilter("error", Warning) # Find out the file location within the sources tree this_module_dir_path = os.path.abspath( os.path.dirname(sys.modules[__name__].__file__)) diff --git a/docs/examples/searching/example.rst b/docs/examples/searching/example.rst index 753c2695..8d2526a3 100644 --- a/docs/examples/searching/example.rst +++ b/docs/examples/searching/example.rst @@ -14,4 +14,4 @@ The following code will show you how to search for functions and variables .. literalinclude:: example.py :language: python - :lines: 5,6,7,14-24,26- \ No newline at end of file + :lines: 5,6,7,16-26,28- diff --git a/docs/examples/searching1/example.py b/docs/examples/searching1/example.py index 4d91a45c..f80a0278 100644 --- a/docs/examples/searching1/example.py +++ b/docs/examples/searching1/example.py @@ -8,6 +8,8 @@ import os import sys +import warnings +warnings.simplefilter("error", Warning) # Find out the file location within the sources tree this_module_dir_path = os.path.abspath( os.path.dirname(sys.modules[__name__].__file__)) diff --git a/docs/examples/searching1/example.rst b/docs/examples/searching1/example.rst index 3104be59..21d8da47 100644 --- a/docs/examples/searching1/example.rst +++ b/docs/examples/searching1/example.rst @@ -14,4 +14,4 @@ The following code will show you how to loop on the tree and find a declaration .. literalinclude:: example.py :language: python - :lines: 5,6,7,14-24,26- \ No newline at end of file + :lines: 5,6,7,16-26,28- diff --git a/docs/examples/variables/example.py b/docs/examples/variables/example.py index a42ab588..8bceda49 100644 --- a/docs/examples/variables/example.py +++ b/docs/examples/variables/example.py @@ -8,6 +8,8 @@ import os import sys +import warnings +warnings.simplefilter("error", Warning) # Find out the file location within the sources tree this_module_dir_path = os.path.abspath( os.path.dirname(sys.modules[__name__].__file__)) diff --git a/docs/examples/variables/example.rst b/docs/examples/variables/example.rst index 574e0bb3..165d6cc4 100644 --- a/docs/examples/variables/example.rst +++ b/docs/examples/variables/example.rst @@ -15,4 +15,4 @@ strategies, and to print information about it: .. literalinclude:: example.py :language: python - :lines: 5,6,7,14-24,26- + :lines: 5,6,7,16-26,28- From aa6854baa2071ffa97e2736de3110a937dd9ae04 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 May 2016 22:51:39 +0200 Subject: [PATCH 140/268] Use .decl_type instead of deprecated .type in variables example --- docs/examples/variables/example.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/examples/variables/example.py b/docs/examples/variables/example.py index 8bceda49..9726814b 100644 --- a/docs/examples/variables/example.py +++ b/docs/examples/variables/example.py @@ -34,14 +34,14 @@ # We know that the c variable is the third one in the list: c = ns.variables()[2] print("My name is: " + c.name) -print("My type is: " + str(c.type)) +print("My type is: " + str(c.decl_type)) print("My value is: " + c.value) # Of course you can also loop over the list and look for the right name for var in ns.variables(): if var.name == "c": print("My name is: " + var.name) - print("My type is: " + str(var.type)) + print("My type is: " + str(var.decl_type)) print("My value is: " + var.value) # One way to get a variable is to use the variable() method and @@ -50,5 +50,5 @@ # specific criteria. c = ns.variable(lambda v: v.name == "c") print("My name is: " + c.name) -print("My type is: " + str(c.type)) +print("My type is: " + str(c.decl_type)) print("My value is: " + c.value) From 6307fb595480c97a3a06190e36ea6ccf081eb3b9 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 May 2016 22:59:06 +0200 Subject: [PATCH 141/268] Deprecate type attribute for calldef arguments Like for the normal declarations, decl_type is the new way to get the type. This prevent overloading of the built-in type function The type attributes will be finally removed in release 1.9.0 --- pygccxml/declarations/calldef.py | 65 ++++++++++++++++------- pygccxml/declarations/decl_printer.py | 2 +- pygccxml/declarations/function_traits.py | 2 +- pygccxml/declarations/matchers.py | 3 +- pygccxml/declarations/type_traits.py | 11 ++-- pygccxml/parser/linker.py | 2 +- pygccxml/parser/patcher.py | 21 ++++---- pygccxml/parser/scanner.py | 2 +- unittests/const_volatile_arg_tester.py | 2 +- unittests/core_tester.py | 3 +- unittests/find_container_traits_tester.py | 3 +- unittests/plain_c_tester.py | 2 +- unittests/vector_traits_tester.py | 2 +- 13 files changed, 76 insertions(+), 44 deletions(-) diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index d0b388ad..c27d9f32 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -17,6 +17,7 @@ - destructor """ import re +import warnings from . import cpptypes from . import algorithm from . import declaration @@ -89,7 +90,7 @@ def clone(self, **keywd): return argument_t( name=keywd.get('name', self.name), - type=keywd.get('type', self.type), + type=keywd.get('type', self.decl_type), default_value=keywd.get('default_value', self.default_value), attributes=keywd.get('attributes', self.attributes )) @@ -97,7 +98,7 @@ def clone(self, **keywd): return argument_t( name=keywd.get( 'name', self.name), type=keywd.get( - 'type', self.type), default_value=keywd.get( + 'type', self.decl_type), default_value=keywd.get( 'default_value', self.default_value), attributes=keywd.get( 'attributes', self.attributes)) @@ -106,22 +107,23 @@ def __str__(self): return "..." else: if self.default_value is None: - return "%s %s" % (self.type, self.name) + return "%s %s" % (self.decl_type, self.name) else: - return "%s %s=%s" % (self.type, self.name, self.default_value) + return "%s %s=%s" % ( + self.decl_type, self.name, self.default_value) def __eq__(self, other): if not isinstance(other, self.__class__): return False return self.name == other.name \ and self.default_value == other.default_value \ - and self.type == other.type + and self.decl_type == other.decl_type def __hash__(self, other): return (hash(self.__class__) ^ hash(self.name) ^ hash(self.default_value) ^ - hash(self.type)) + hash(self.decl_type)) def __ne__(self, other): return not self.__eq__(other) @@ -131,7 +133,7 @@ def __lt__(self, other): return self.__class__.__name__ < other.__class__.__name__ return self.name < other.name \ and self.default_value < other.default_value \ - and self.type < other.type + and self.decl_type < other.decl_type @property def name(self): @@ -147,7 +149,7 @@ def name(self, name): def ellipsis(self): """bool, if True argument represents ellipsis ( "..." ) in function definition""" - return isinstance(self.type, cpptypes.ellipsis_t) + return isinstance(self.decl_type, cpptypes.ellipsis_t) @property def default_value(self): @@ -161,12 +163,35 @@ def default_value(self, default_value): @property def type(self): - """The argument :class:`type `""" + """ + Deprecated since v1.8.0. Will be removed in v1.9.0 + + """ + + warnings.warn( + "argument_t.type is deprecated.\n" + + "Please use argument_t.decl_type instead.", DeprecationWarning) return self._type @type.setter - def type(self, type): - self._type = type + def type(self, _type): + """ + Deprecated since v1.8.0. Will be removed in v1.9.0 + + """ + + warnings.warn( + "argument_t.type is deprecated.\n" + + "Please use argument_t.decl_type instead.", DeprecationWarning) + self._type = _type + + @property + def decl_type(self): + return self._type + + @decl_type.setter + def decl_type(self, decl_type): + self._type = decl_type @property def attributes(self): @@ -291,7 +316,7 @@ def has_ellipsis(self): @property def argument_types(self): """list of all argument types""" - return [arg.type for arg in self.arguments] + return [arg.decl_type for arg in self.arguments] @property def required_args(self): @@ -460,7 +485,7 @@ def i_depend_on_them(self, recursive=True): answer.append( self._report(self.return_type, hint="return type")) for arg in self.arguments: - answer.append(self._report(arg.type)) + answer.append(self._report(arg.decl_type)) for exc in self.exceptions: answer.append(self._report(exc, hint="exception")) return answer @@ -600,12 +625,12 @@ def function_type(self): if self.has_static: return cpptypes.free_function_type_t( return_type=self.return_type, - arguments_types=[arg.type for arg in self.arguments]) + arguments_types=[arg.decl_type for arg in self.arguments]) else: return cpptypes.member_function_type_t( class_inst=self.parent, return_type=self.return_type, - arguments_types=[arg.type for arg in self.arguments], + arguments_types=[arg.decl_type for arg in self.arguments], has_const=self.has_const) def create_decl_string(self, with_defaults=True): @@ -660,7 +685,7 @@ def function_type(self): return cpptypes.free_function_type_t( return_type=self.return_type, arguments_types=[ - arg.type for arg in self.arguments]) + arg.decl_type for arg in self.arguments]) def create_decl_string(self, with_defaults=True): f_type = self.function_type() @@ -753,7 +778,7 @@ def is_copy_constructor(self): # We have only one argument, get it arg = args[0] - if not isinstance(arg.type, cpptypes.compound_t): + if not isinstance(arg.decl_type, cpptypes.compound_t): # An argument of type declarated_t (a typedef) could be passed to # the constructor; and it could be a reference. # But in c++ you can NOT write : @@ -765,14 +790,14 @@ def is_copy_constructor(self): return False # The argument needs to be passed by reference in a copy constructor - if not type_traits.is_reference(arg.type): + if not type_traits.is_reference(arg.decl_type): return False # The argument needs to be const for a copy constructor - if not type_traits.is_const(arg.type.base): + if not type_traits.is_const(arg.decl_type.base): return False - un_aliased = type_traits.remove_alias(arg.type.base) + un_aliased = type_traits.remove_alias(arg.decl_type.base) # un_aliased now refers to const_t instance if not isinstance(un_aliased.base, cpptypes.declarated_t): # We are looking for a declaration diff --git a/pygccxml/declarations/decl_printer.py b/pygccxml/declarations/decl_printer.py index b93ef154..34d7185d 100644 --- a/pygccxml/declarations/decl_printer.py +++ b/pygccxml/declarations/decl_printer.py @@ -202,7 +202,7 @@ def print_calldef_info(self, decl=None): retval = decl.return_type.decl_string args = [] for arg in decl.arguments: - args.append(arg.type.decl_string + ' ' + arg.name) + args.append(arg.decl_type.decl_string + ' ' + arg.name) indent = ' ' * (self.level + 1) * self.INDENT_SIZE self.writer(indent + "is extern: " + str(decl.has_extern)) self.writer(indent + "return type: " + str(retval)) diff --git a/pygccxml/declarations/function_traits.py b/pygccxml/declarations/function_traits.py index 15629f6a..ba7fa739 100644 --- a/pygccxml/declarations/function_traits.py +++ b/pygccxml/declarations/function_traits.py @@ -87,6 +87,6 @@ def is_same_function(f1, f2): if len(f1.arguments) != len(f2.arguments): return False for f1_arg, f2_arg in zip(f1.arguments, f2.arguments): - if not type_traits.is_same(f1_arg.type, f2_arg.type): + if not type_traits.is_same(f1_arg.decl_type, f2_arg.decl_type): return False return True diff --git a/pygccxml/declarations/matchers.py b/pygccxml/declarations/matchers.py index cc95868e..652deaf2 100644 --- a/pygccxml/declarations/matchers.py +++ b/pygccxml/declarations/matchers.py @@ -426,7 +426,8 @@ def __call__(self, decl): if type_or_str is None: continue else: - if not self.__compare_types(type_or_str, arg.type): + if not self.__compare_types( + type_or_str, arg.decl_type): return False return True diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 7e377bef..f8fc36f5 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -35,7 +35,7 @@ def __remove_alias(type_): """implementation details""" if isinstance(type_, typedef.typedef_t): - return __remove_alias(type_.type) + return __remove_alias(type_.decl_type) if isinstance(type_, cpptypes.declarated_t) and \ isinstance(type_.declaration, typedef.typedef_t): return __remove_alias(type_.declaration.decl_type) @@ -640,7 +640,7 @@ def is_unary_operator(oper): if 0 == len(oper.arguments): return True elif oper.symbol in ['++', '--'] and \ - isinstance(oper.arguments[0].type, cpptypes.int_t): + isinstance(oper.arguments[0].decl_type, cpptypes.int_t): return True else: return False @@ -649,7 +649,7 @@ def is_unary_operator(oper): return True elif oper.symbol in ['++', '--'] \ and 2 == len(oper.arguments) \ - and isinstance(oper.arguments[1].type, cpptypes.int_t): + and isinstance(oper.arguments[1].decl_type, cpptypes.int_t): # may be I need to add additional check whether first argument is # reference or not? return True @@ -971,7 +971,7 @@ def is_convertible(self): continue # TODO: add test to check explicitness if is_convertible(source, - constructor.arguments[0].type): + constructor.arguments[0].decl_type): return True return False @@ -1191,7 +1191,8 @@ class internal_type_traits(object): def get_by_name(type_, name): if class_traits.is_my_case(type_): cls = class_traits.declaration_class(type_) - return remove_declarated(cls.typedef(name, recursive=False).type) + return remove_declarated( + cls.typedef(name, recursive=False).decl_type) elif class_declaration_traits.is_my_case(type_): cls = class_declaration_traits.get_declaration(type_) value_type_str = templates.args(cls.name)[0] diff --git a/pygccxml/parser/linker.py b/pygccxml/parser/linker.py index 6127522f..e513fdff 100644 --- a/pygccxml/parser/linker.py +++ b/pygccxml/parser/linker.py @@ -86,7 +86,7 @@ def __link_calldef(self): self.__inst.arguments_types = linked_args else: for arg in self.__inst.arguments: - arg.type = self.__link_type(arg.type) + arg.decl_type = self.__link_type(arg.decl_type) for i, exception in enumerate(self.__inst.exceptions): try: self.__inst.exceptions[i] = self.__decls[exception] diff --git a/pygccxml/parser/patcher.py b/pygccxml/parser/patcher.py index 489dc8db..19fddf34 100644 --- a/pygccxml/parser/patcher.py +++ b/pygccxml/parser/patcher.py @@ -42,7 +42,8 @@ def __join_names(self, prefix, suffix): return prefix + '::' + suffix def __is_unqualified_enum(self, func, arg): - type_ = declarations.remove_reference(declarations.remove_cv(arg.type)) + type_ = declarations.remove_reference( + declarations.remove_cv(arg.decl_type)) if not declarations.is_enum(type_): return False enum_type = declarations.enum_declaration(type_) @@ -53,7 +54,8 @@ def __is_unqualified_enum(self, func, arg): arg.default_value.split('::')[-1]) def __fix_unqualified_enum(self, func, arg): - type_ = declarations.remove_reference(declarations.remove_cv(arg.type)) + type_ = declarations.remove_reference( + declarations.remove_cv(arg.decl_type)) enum_type = declarations.enum_declaration(type_) if self.__cxx_std.is_cxx11_or_greater: qualifier_decl_string = enum_type.decl_string @@ -64,7 +66,8 @@ def __fix_unqualified_enum(self, func, arg): arg.default_value.split('::')[-1]) def __is_invalid_integral(self, func, arg): - type_ = declarations.remove_reference(declarations.remove_cv(arg.type)) + type_ = declarations.remove_reference( + declarations.remove_cv(arg.decl_type)) if not declarations.is_integral(type_): return False try: @@ -107,8 +110,8 @@ def __fix_invalid_integral(self, func, arg): while parent: found = self.__find_enum(parent, enum_value) if found: - if declarations.is_fundamental(arg.type) and ' ' in \ - arg.type.decl_string: + if declarations.is_fundamental(arg.decl_type) and ' ' in \ + arg.decl_type.decl_string: template = '(%s)(%s)' else: template = '%s(%s)' @@ -116,7 +119,7 @@ def __fix_invalid_integral(self, func, arg): qualifier_decl_string = found.decl_string else: qualifier_decl_string = found.parent.decl_string - return template % (arg.type.decl_string, + return template % (arg.decl_type.decl_string, self.__join_names(qualifier_decl_string, enum_value)) else: @@ -135,7 +138,7 @@ def __fix_invalid_integral(self, func, arg): except declarations.matcher.declaration_not_found_t: # ignore exceptions if a match is not found found = None - if found and declarations.is_fundamental(arg.type): + if found and declarations.is_fundamental(arg.decl_type): return "%s" % self.__join_names( found.parent.decl_string, arg.default_value) parent = parent.parent @@ -182,7 +185,7 @@ def __is_constructor_call(self, func, arg): if not call_invocation.is_call_invocation(dv): return False name = call_invocation.name(dv) - base_type = declarations.base_type(arg.type) + base_type = declarations.base_type(arg.decl_type) if not isinstance(base_type, declarations.declarated_t): return False decl = base_type.declaration @@ -196,7 +199,7 @@ def __fix_constructor_call(self, func, arg): dv = arg.default_value if not call_invocation.is_call_invocation(dv): return False - base_type = declarations.base_type(arg.type) + base_type = declarations.base_type(arg.decl_type) decl = base_type.declaration name, args = call_invocation.split(dv) if decl.name != name: diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index 4ba3d75c..3bff284c 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -451,7 +451,7 @@ def __read_argument(self, attrs): XML_AN_NAME, 'arg%d' % len( self.__inst.arguments)) - argument.type = attrs[XML_AN_TYPE] + argument.decl_type = attrs[XML_AN_TYPE] argument.default_value = attrs.get(XML_AN_DEFAULT) self.__read_attributes(argument, attrs) if 'CastXML' not in utils.xml_generator: diff --git a/unittests/const_volatile_arg_tester.py b/unittests/const_volatile_arg_tester.py index 623d5b79..6ec459ec 100644 --- a/unittests/const_volatile_arg_tester.py +++ b/unittests/const_volatile_arg_tester.py @@ -26,7 +26,7 @@ def setUp(self): def test(self): f = self.global_ns.free_fun('pygccxml_bug') - t = f.arguments[0].type + t = f.arguments[0].decl_type self.assertTrue(isinstance(t, declarations.pointer_t)) self.assertTrue(isinstance(t.base, declarations.volatile_t)) self.assertTrue(isinstance(t.base.base, declarations.const_t)) diff --git a/unittests/core_tester.py b/unittests/core_tester.py index 723dc2e2..e079ad93 100644 --- a/unittests/core_tester.py +++ b/unittests/core_tester.py @@ -340,7 +340,8 @@ def test_fundamental_types(self): errors.append( "there is a difference between typedef base type " + "name('%s') and expected one('%s')" % - (typedef.type.decl_string, fundamental_type.decl_string)) + (typedef.decl_type.decl_string, + fundamental_type.decl_string)) self.assertFalse(errors, pprint.pformat(errors)) def test_compound_types(self): diff --git a/unittests/find_container_traits_tester.py b/unittests/find_container_traits_tester.py index bd7284a4..9cad6cdb 100644 --- a/unittests/find_container_traits_tester.py +++ b/unittests/find_container_traits_tester.py @@ -148,7 +148,8 @@ def test_multimap(self): def test_recursive_partial_name(self): f1 = self.global_ns.free_fun('f1') - t1 = declarations.class_traits.get_declaration(f1.arguments[0].type) + t1 = declarations.class_traits.get_declaration( + f1.arguments[0].decl_type) self.assertTrue( 'type< std::set< std::vector< int > > >' == t1.partial_name) diff --git a/unittests/plain_c_tester.py b/unittests/plain_c_tester.py index 511aa62f..99e2aeb7 100644 --- a/unittests/plain_c_tester.py +++ b/unittests/plain_c_tester.py @@ -27,7 +27,7 @@ def test(self): self.global_ns.free_fun('hello_print') f = self.global_ns.free_fun('do_smth') for arg in f.arguments: - self.assertTrue(arg.type.decl_string) + self.assertTrue(arg.decl_type.decl_string) def create_suite(): diff --git a/unittests/vector_traits_tester.py b/unittests/vector_traits_tester.py index 429ba427..6d01fb46 100644 --- a/unittests/vector_traits_tester.py +++ b/unittests/vector_traits_tester.py @@ -74,7 +74,7 @@ def test_element_type(self): do_nothing = self.global_ns.free_fun('do_nothing') v = declarations.remove_reference( declarations.remove_declarated( - do_nothing.arguments[0].type)) + do_nothing.arguments[0].decl_type)) declarations.vector_traits.element_type(v) From e98d510476c2d942dfa3ff8d274a5a5fc8bc4fff Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 May 2016 23:00:38 +0200 Subject: [PATCH 142/268] Use decl_type in undname.py This part of code is untested (and unused ?), but now that all the type attributes are deprecated (for declarations and called arguments), we can safely replace it. --- pygccxml/binary_parsers/undname.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygccxml/binary_parsers/undname.py b/pygccxml/binary_parsers/undname.py index b3c764c5..d5568891 100644 --- a/pygccxml/binary_parsers/undname.py +++ b/pygccxml/binary_parsers/undname.py @@ -234,7 +234,7 @@ def format_var(self, decl, hint): result.append('static ') if hint == 'msvc': result.append( - self.__format_type_as_undecorated(decl.type, False, hint)) + self.__format_type_as_undecorated(decl.decl_type, False, hint)) result.append(' ') if is_mem_var: result.append( From 8e0e357c56a0f36753e4303a2d0dea62766f672c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 11 May 2016 23:07:57 +0200 Subject: [PATCH 143/268] Do not overload built-in type function --- pygccxml/declarations/algorithm.py | 6 +++--- pygccxml/declarations/matchers.py | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pygccxml/declarations/algorithm.py b/pygccxml/declarations/algorithm.py index b089c8f0..f6c3e718 100644 --- a/pygccxml/declarations/algorithm.py +++ b/pygccxml/declarations/algorithm.py @@ -227,7 +227,7 @@ class match_declaration_t(object): """ def __init__(self, type=None, name=None, fullname=None, parent=None): - self.type = type + self._type = type self.name = name self.fullname = fullname self.parent = parent @@ -244,8 +244,8 @@ def does_match_exist(self, inst): """ answer = True - if self.type is not None: - answer &= isinstance(inst, self.type) + if self._type is not None: + answer &= isinstance(inst, self._type) if self.name is not None: answer &= inst.name == self.name if self.parent is not None: diff --git a/pygccxml/declarations/matchers.py b/pygccxml/declarations/matchers.py index 652deaf2..d86c5009 100644 --- a/pygccxml/declarations/matchers.py +++ b/pygccxml/declarations/matchers.py @@ -317,17 +317,17 @@ def __init__( decl_type=variable.variable_t, header_dir=header_dir, header_file=header_file) - self.type = type + self._type = type def __call__(self, decl): if not super(variable_matcher_t, self).__call__(decl): return False - if self.type is not None: - if isinstance(self.type, cpptypes.type_t): - if self.type != decl.decl_type: + if self._type is not None: + if isinstance(self._type, cpptypes.type_t): + if self._type != decl.decl_type: return False else: - if self.type != decl.decl_type.decl_string: + if self._type != decl.decl_type.decl_string: return False return True @@ -335,8 +335,8 @@ def __str__(self): msg = [super(variable_matcher_t, self).__str__()] if msg == ['any']: msg = [] - if self.type is not None: - msg.append('(value type==%s)' % str(self.type)) + if self._type is not None: + msg.append('(value type==%s)' % str(self._type)) if not msg: msg.append('any') return ' and '.join(msg) From 12ab4c17c2925aaa81a0cf73229e22729177b880 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 12 May 2016 23:41:43 +0200 Subject: [PATCH 144/268] Fix failing tests under ubuntu wily (see #47) The __castxml__ definition does not exist with the castxml shipped with wily. In this case, do not use it and check for __GCCXML__ instead, to know which xml generator we are using. The travis build was not getting this error because we are using one of the latest versions of CastXML there instead of the one shipped by apt. Reorganised the definitions to make more sense. --- unittests/data/remove_template_defaults.hpp | 52 +++++++++++---------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/unittests/data/remove_template_defaults.hpp b/unittests/data/remove_template_defaults.hpp index ba51113e..46496ced 100644 --- a/unittests/data/remove_template_defaults.hpp +++ b/unittests/data/remove_template_defaults.hpp @@ -35,13 +35,33 @@ #else - // This is mostly for GCCXML (when using old compilers) + #if defined( __GCCXML__ ) + + #if defined( __GNUC__ ) + #include + #include + #define HASH_XXX_NS __gnu_cxx + #else + #include + #include + #if !defined( __PYGCCXML_MSVC9__ ) + #define HASH_XXX_NS std + #else + #define HASH_XXX_NS stdext + #endif + + #endif + + #define HASH_XXX_UMAP hash_map + #define HASH_XXX_USET hash_set + #define HASH_XXX_UMMAP hash_multimap + #define HASH_XXX_UMMSET hash_multiset + + #else - #if defined( __GNUC__ ) #if ((__GNUC__ > 4) || \ (__GNUC__ == 4 && __GNUC_MINOR__ > 4) || \ - (__GNUC__ == 4 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ == 7)) && \ - defined(__castxml__) + (__GNUC__ == 4 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ == 7)) // Use TR1 containers for gcc >= 4.4.7 + castxml // (this might work on older versions of gcc too, needs testing) @@ -54,28 +74,10 @@ #define HASH_XXX_UMMAP unordered_multimap #define HASH_XXX_UMMSET unordered_multiset #else - #include - #include - #define HASH_XXX_NS __gnu_cxx - - #define HASH_XXX_UMAP hash_map - #define HASH_XXX_USET hash_set - #define HASH_XXX_UMMAP hash_multimap - #define HASH_XXX_UMMSET hash_multiset + // Older versions of gcc are not tested. + // 4.4.7 is already quite old. + #error "Not tested" #endif - #else - #include - #include - #if defined( __GCCXML__ ) && !defined( __PYGCCXML_MSVC9__ ) - #define HASH_XXX_NS std - #else - #define HASH_XXX_NS stdext - #endif - - #define HASH_XXX_UMAP hash_map - #define HASH_XXX_USET hash_set - #define HASH_XXX_UMMAP hash_multimap - #define HASH_XXX_UMMSET hash_multiset #endif #endif From 9d233ff86e2d54a6c7ded08715caf0723f2eddbc Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 12 May 2016 23:50:22 +0200 Subject: [PATCH 145/268] Cleanup and fix annotate test (#25) The annotate mechanism is working correctly with newer versions of CastXML Check for it only with a version >= 1.137 --- unittests/attributes_tester.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/unittests/attributes_tester.py b/unittests/attributes_tester.py index 9b9c27cb..3ed81cb8 100644 --- a/unittests/attributes_tester.py +++ b/unittests/attributes_tester.py @@ -16,6 +16,8 @@ class tester_t(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) + # TODO: once gccxml is removed; rename this to something like + # annotate_tester self.header = "attributes_" + self.config.xml_generator + ".hpp" def setUp(self): @@ -26,24 +28,24 @@ def setUp(self): def test(self): - if "CastXML" in utils.xml_generator: - prefix = "annotate" - else: - prefix = "gccxml" - numeric = self.global_ns.class_('numeric_t') - - # Dependending on the compiler, this attribute will be found - # or not: never on OS X (clang and gcc), - # always on ubuntu (clang and gcc). Just skip this test for the - # moment. - - # self.assertTrue(None is numeric.attributes) - do_nothing = numeric.mem_fun('do_nothing') - self.assertTrue((prefix + "(no throw)") == do_nothing.attributes) arg = do_nothing.arguments[0] - self.assertTrue((prefix + "(out)") == arg.attributes) + + if "CastXML" in utils.xml_generator: + if utils.xml_output_version >= 1.137: + # This works since: + # https://github.com/CastXML/CastXML/issues/25 + # https://github.com/CastXML/CastXML/pull/26 + # https://github.com/CastXML/CastXML/pull/27 + # The version bump to 1.137 came way later but this is the + # only way to make sure the test is running correctly + self.assertTrue("annotate(sealed)" == numeric.attributes) + self.assertTrue("annotate(no throw)" == do_nothing.attributes) + self.assertTrue("annotate(out)" == arg.attributes) + else: + self.assertTrue("gccxml(no throw)" == do_nothing.attributes) + self.assertTrue("gccxml(out)" == arg.attributes) def create_suite(): From 53afbedc23a65fb8db0d21aaf2971b1d9dd1fe3c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 29 May 2016 11:50:11 +0200 Subject: [PATCH 146/268] Deprecate type arguments, replace them by decl_type type can still be used, but will be removed in pygccxml 1.9.0 This makes it consistent with the getters/setters that have been changed to decl_type lately, preventing the overloading of the type built-in function. --- docs/examples/searching/example.py | 2 +- pygccxml/declarations/matchers.py | 34 ++++++++++++++++++++-------- pygccxml/declarations/scopedef.py | 33 +++++++++++++++++++++++++-- pygccxml/declarations/typedef.py | 31 +++++++++++++++++-------- pygccxml/declarations/variable.py | 26 ++++++++++++++++----- pygccxml/parser/scanner.py | 4 ++-- unittests/variable_matcher_tester.py | 4 ++-- 7 files changed, 103 insertions(+), 31 deletions(-) diff --git a/docs/examples/searching/example.py b/docs/examples/searching/example.py index 1ef7b35d..ba596254 100644 --- a/docs/examples/searching/example.py +++ b/docs/examples/searching/example.py @@ -74,7 +74,7 @@ criteria = declarations.variable_matcher(name="a") var_a1 = declarations.matcher.find(criteria, ns_namespace) -criteria = declarations.variable_matcher(type=int_type) +criteria = declarations.variable_matcher(decl_type=int_type) var_a2 = declarations.matcher.find(criteria, ns_namespace) print(var_a1[0]) diff --git a/pygccxml/declarations/matchers.py b/pygccxml/declarations/matchers.py index d86c5009..387190e7 100644 --- a/pygccxml/declarations/matchers.py +++ b/pygccxml/declarations/matchers.py @@ -10,6 +10,7 @@ import os import re +import warnings from . import algorithm from . import variable from . import namespace @@ -305,29 +306,44 @@ def __init__( self, name=None, type=None, + decl_type=None, header_dir=None, header_file=None): """ - :param type: variable type - :type type: string or instance of :class:`type_t` derived class + :param decl_type: variable type + :type decl_type: string or instance of :class:`type_t` derived class """ + + if type is not None: + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type + declaration_matcher_t.__init__( self, name=name, decl_type=variable.variable_t, header_dir=header_dir, header_file=header_file) - self._type = type + self._decl_type = decl_type def __call__(self, decl): if not super(variable_matcher_t, self).__call__(decl): return False - if self._type is not None: - if isinstance(self._type, cpptypes.type_t): - if self._type != decl.decl_type: + if self._decl_type is not None: + if isinstance(self._decl_type, cpptypes.type_t): + if self._decl_type != decl.decl_type: return False else: - if self._type != decl.decl_type.decl_string: + if self._decl_type != decl.decl_type.decl_string: return False return True @@ -335,8 +351,8 @@ def __str__(self): msg = [super(variable_matcher_t, self).__str__()] if msg == ['any']: msg = [] - if self._type is not None: - msg.append('(value type==%s)' % str(self._type)) + if self._decl_type is not None: + msg.append('(value type==%s)' % str(self._decl_type)) if not msg: msg.append('any') return ' and '.join(msg) diff --git a/pygccxml/declarations/scopedef.py b/pygccxml/declarations/scopedef.py index f1556dd8..1c93db25 100644 --- a/pygccxml/declarations/scopedef.py +++ b/pygccxml/declarations/scopedef.py @@ -504,18 +504,32 @@ def variable( name=None, function=None, type=None, + decl_type=None, header_dir=None, header_file=None, recursive=None): """returns reference to variable declaration, that is matched defined criteria""" + if type is not None: + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type + return ( self._find_single( self._impl_matchers[ scopedef_t.variable], name=name, function=function, - type=type, + decl_type=decl_type, header_dir=header_dir, header_file=header_file, recursive=recursive) @@ -546,10 +560,25 @@ def variables( name=None, function=None, type=None, + decl_type=None, header_dir=None, header_file=None, recursive=None, allow_empty=None): + + # Deprecated since 1.8.0. Will be removed in 1.9.0 + if type is not None: + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type + """returns a set of variable declarations, that are matched defined criteria""" return ( @@ -558,7 +587,7 @@ def variables( scopedef_t.variable], name=name, function=function, - type=type, + decl_type=decl_type, header_dir=header_dir, header_file=header_file, recursive=recursive, diff --git a/pygccxml/declarations/typedef.py b/pygccxml/declarations/typedef.py index b73c68de..485e186f 100644 --- a/pygccxml/declarations/typedef.py +++ b/pygccxml/declarations/typedef.py @@ -16,10 +16,23 @@ class typedef_t(declaration.declaration_t): """describes C++ typedef declaration""" - def __init__(self, name='', type=None): + def __init__(self, name='', type=None, decl_type=None): """creates class that describes C++ typedef""" + + if type is not None: + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type + declaration.declaration_t.__init__(self, name) - self._type = type + self._decl_type = decl_type def _get__cmp__items(self): """implementation details""" @@ -43,10 +56,10 @@ def type(self): warnings.warn( "typedef_t.type is deprecated.\n" + "Please use typedef_t.decl_type instead.", DeprecationWarning) - return self._type + return self._decl_type @type.setter - def type(self, _type): + def type(self, _decl_type): """ Deprecated since v1.8.0. Will be removed in v1.9.0 @@ -55,16 +68,16 @@ def type(self, _type): warnings.warn( "typedef_t.type is deprecated.\n" + "Please use typedef_t.decl_type instead.", DeprecationWarning) - self._type = _type + self._decl_type = _decl_type @property def decl_type(self): """reference to the original :class:`decl_type `""" - return self._type + return self._decl_type @decl_type.setter def decl_type(self, decl_type): - self._type = decl_type + self._decl_type = decl_type def i_depend_on_them(self, recursive=True): return [dependencies.dependency_info_t(self, self.decl_type)] @@ -72,9 +85,9 @@ def i_depend_on_them(self, recursive=True): @property def byte_size(self): """Size of this type in bytes @type: int""" - return self._type.byte_size + return self._decl_type.byte_size @property def byte_align(self): """alignment of this type in bytes @type: int""" - return self._type.byte_align + return self._decl_type.byte_align diff --git a/pygccxml/declarations/variable.py b/pygccxml/declarations/variable.py index 3c15948e..f5e96898 100644 --- a/pygccxml/declarations/variable.py +++ b/pygccxml/declarations/variable.py @@ -21,13 +21,27 @@ def __init__( self, name='', type=None, + decl_type=None, type_qualifiers=None, value=None, bits=None, mangled=None): """creates class that describes C++ global or member variable""" + + if type is not None: + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type + declaration.declaration_t.__init__(self, name) - self._type = type + self._decl_type = decl_type self._type_qualifiers = type_qualifiers self._value = value self._bits = bits @@ -59,10 +73,10 @@ def type(self): warnings.warn( "variable_t.type is deprecated.\n" + "Please use variable_t.decl_type instead.", DeprecationWarning) - return self._type + return self._decl_type @type.setter - def type(self, _type): + def type(self, _decl_type): """ Deprecated since v1.8.0. Will be removed in v1.9.0 @@ -70,16 +84,16 @@ def type(self, _type): warnings.warn( "variable_t.type is deprecated.\n" + "Please use variable_t.decl_type instead.", DeprecationWarning) - self._type = _type + self._decl_type = _decl_type @property def decl_type(self): """reference to the variable :class:`decl_type `""" - return self._type + return self._decl_type @decl_type.setter def decl_type(self, decl_type): - self._type = decl_type + self._decl_type = decl_type @property def type_qualifiers(self): diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index 3bff284c..75822754 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -515,7 +515,7 @@ def __read_typedef(self, attrs): name=attrs.get( XML_AN_NAME, ''), - type=attrs[XML_AN_TYPE]) + decl_type=attrs[XML_AN_TYPE]) def __read_variable(self, attrs): type_qualifiers = declarations.type_qualifiers_t() @@ -528,7 +528,7 @@ def __read_variable(self, attrs): name=attrs.get( XML_AN_NAME, ''), - type=attrs[XML_AN_TYPE], + decl_type=attrs[XML_AN_TYPE], type_qualifiers=type_qualifiers, value=attrs.get( XML_AN_INIT), diff --git a/unittests/variable_matcher_tester.py b/unittests/variable_matcher_tester.py index 84a5369b..fcb9881c 100644 --- a/unittests/variable_matcher_tester.py +++ b/unittests/variable_matcher_tester.py @@ -26,7 +26,7 @@ def setUp(self): def test(self): criteria = declarations.variable_matcher_t( name='x', - type='unsigned int') + decl_type='unsigned int') x = declarations.matcher.get_single(criteria, self.declarations) comp_str = ( @@ -36,7 +36,7 @@ def test(self): criteria = declarations.variable_matcher_t( name='::bit_fields::fields_t::x', - type=declarations.unsigned_int_t(), + decl_type=declarations.unsigned_int_t(), header_dir=os.path.dirname( x.location.file_name), header_file=x.location.file_name) From 9aa9cc25cbb222f1d1189e61c5828d0d82ea2c00 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 29 May 2016 13:45:27 +0200 Subject: [PATCH 147/268] Deprecate more type arguments Please use decl_type instead. The type argument is still usable in pygccxml 1.8.0 and will be removed in version 1.9.0 --- pygccxml/declarations/algorithm.py | 83 ++++++++++++++++++++++++---- pygccxml/declarations/type_traits.py | 6 +- pygccxml/parser/project_reader.py | 2 +- unittests/text_reader_tester.py | 2 +- unittests/type_traits_tester.py | 40 +++++++------- unittests/typedefs_tester.py | 4 +- 6 files changed, 99 insertions(+), 38 deletions(-) diff --git a/pygccxml/declarations/algorithm.py b/pygccxml/declarations/algorithm.py index f6c3e718..1df6e9b2 100644 --- a/pygccxml/declarations/algorithm.py +++ b/pygccxml/declarations/algorithm.py @@ -8,6 +8,8 @@ """ +import warnings + def declaration_path(decl, with_defaults=True): """ @@ -226,8 +228,24 @@ class match_declaration_t(object): """ - def __init__(self, type=None, name=None, fullname=None, parent=None): - self._type = type + def __init__( + self, type=None, decl_type=None, + name=None, fullname=None, parent=None): + + if type is not None: + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type + + self._decl_type = decl_type self.name = name self.fullname = fullname self.parent = parent @@ -244,8 +262,8 @@ def does_match_exist(self, inst): """ answer = True - if self._type is not None: - answer &= isinstance(inst, self._type) + if self._decl_type is not None: + answer &= isinstance(inst, self._decl_type) if self.name is not None: answer &= inst.name == self.name if self.parent is not None: @@ -271,6 +289,7 @@ def __call__(self, inst): def find_all_declarations( declarations, type=None, + decl_type=None, name=None, parent=None, recursive=True, @@ -285,6 +304,18 @@ def find_all_declarations( :rtype: [ matched declarations ] """ + if type is not None: + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type if recursive: decls = make_flatten(declarations) @@ -294,16 +325,17 @@ def find_all_declarations( return list( filter( match_declaration_t( - type, - name, - fullname, - parent), + decl_type=decl_type, + name=name, + fullname=fullname, + parent=parent), decls)) def find_declaration( declarations, type=None, + decl_type=None, name=None, parent=None, recursive=True, @@ -318,10 +350,22 @@ def find_declaration( :rtype: matched declaration :class:`declaration_t` or None """ + if type is not None: + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type decl = find_all_declarations( declarations, - type=type, + decl_type=decl_type, name=name, parent=parent, recursive=recursive, @@ -333,6 +377,7 @@ def find_declaration( def find_first_declaration( declarations, type=None, + decl_type=None, name=None, parent=None, recursive=True, @@ -346,8 +391,24 @@ def find_first_declaration( :rtype: matched declaration :class:`declaration_t` or None """ - - matcher = match_declaration_t(type, name, fullname, parent) + if type is not None: + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type + + matcher = match_declaration_t( + decl_type=decl_type, + name=name, + fullname=fullname, + parent=parent) if recursive: decls = make_flatten(declarations) else: diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index f8fc36f5..4519ccc6 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -696,7 +696,7 @@ def __find_class_by_class_declaration(self, class_decl): found = algorithm.find_declaration( class_decl.parent.declarations, name=class_decl.name, - type=class_declaration.class_t) + decl_type=class_declaration.class_t) return found def __normalize(self, type_): @@ -950,7 +950,7 @@ def is_convertible(self): # has operator casting_operators = algorithm.find_all_declarations( source_inst.declarations, - type=calldef.casting_operator_t, + decl_type=calldef.casting_operator_t, recursive=False) if casting_operators: for operator in casting_operators: @@ -963,7 +963,7 @@ def is_convertible(self): if isinstance(target.declaration, class_declaration.class_t): constructors = algorithm.find_all_declarations( target.declaration.declarations, - type=calldef.constructor_t, + decl_type=calldef.constructor_t, recursive=False) if constructors: for constructor in constructors: diff --git a/pygccxml/parser/project_reader.py b/pygccxml/parser/project_reader.py index 30c1cddc..5142b89d 100644 --- a/pygccxml/parser/project_reader.py +++ b/pygccxml/parser/project_reader.py @@ -402,7 +402,7 @@ def _join_top_namespaces(main_ns_list, other_ns_list): for other_ns in other_ns_list: main_ns = pygccxml.declarations.find_declaration( answer, - type=pygccxml.declarations.namespace_t, + decl_type=pygccxml.declarations.namespace_t, name=other_ns._name, recursive=False) if main_ns: diff --git a/unittests/text_reader_tester.py b/unittests/text_reader_tester.py index 6175f97a..9e0b97f4 100644 --- a/unittests/text_reader_tester.py +++ b/unittests/text_reader_tester.py @@ -26,7 +26,7 @@ def test(self): compilation_mode=parser.COMPILATION_MODE.FILE_BY_FILE) var_i = declarations.find_declaration( - decls, type=declarations.variable_t, name='i') + decls, decl_type=declarations.variable_t, name='i') self.assertTrue(var_i, "Variable i has not been found.") diff --git a/unittests/type_traits_tester.py b/unittests/type_traits_tester.py index 93200abd..dba7a24e 100644 --- a/unittests/type_traits_tester.py +++ b/unittests/type_traits_tester.py @@ -29,17 +29,17 @@ def setUp(self): def __test_type_category(self, ns_name, controller): ns_control = declarations.find_declaration( self.declarations, - type=declarations.namespace_t, + decl_type=declarations.namespace_t, name=ns_name) self.assertTrue(ns_control, "unable to find '%s' namespace" % ns_name) ns_yes = declarations.find_declaration( ns_control, - type=declarations.namespace_t, + decl_type=declarations.namespace_t, name='yes') self.assertTrue(ns_yes, "unable to find 'yes' namespace") ns_no = declarations.find_declaration( ns_control, - type=declarations.namespace_t, + decl_type=declarations.namespace_t, name='no') self.assertTrue(ns_no, "unable to find 'no' namespace") er = 'for type "%s" the answer to the question "%s" should be True' @@ -74,17 +74,17 @@ def __test_type_category(self, ns_name, controller): def __test_type_transformation(self, ns_name, transformer): ns_control = declarations.find_declaration( self.declarations, - type=declarations.namespace_t, + decl_type=declarations.namespace_t, name=ns_name) self.assertTrue(ns_control, "unable to find '%s' namespace" % ns_name) ns_before = declarations.find_declaration( ns_control, - type=declarations.namespace_t, + decl_type=declarations.namespace_t, name='before') self.assertTrue(ns_before, "unable to find 'before' namespace") ns_after = declarations.find_declaration( ns_control, - type=declarations.namespace_t, + decl_type=declarations.namespace_t, name='after') self.assertTrue(ns_after, "unable to find 'after' namespace") @@ -189,16 +189,16 @@ def test_has_copy_constructor(self): def test_is_base_and_derived(self): ns = declarations.find_declaration( self.declarations, - type=declarations.namespace_t, + decl_type=declarations.namespace_t, name='is_base_and_derived') self.assertTrue(ns, "unable to find 'is_base_and_derived' namespace") base = declarations.find_declaration( ns.declarations, - type=declarations.class_t, + decl_type=declarations.class_t, name='base') derived = declarations.find_declaration( ns.declarations, - type=declarations.class_t, + decl_type=declarations.class_t, name='derived') self.assertTrue( base and derived and declarations.is_base_and_derived( @@ -210,12 +210,12 @@ def test_is_base_and_derived(self): unrelated1 = declarations.find_declaration( ns.declarations, - type=declarations.class_t, + decl_type=declarations.class_t, name='unrelated1') unrelated2 = declarations.find_declaration( ns.declarations, - type=declarations.class_t, + decl_type=declarations.class_t, name='unrelated2') self.assertTrue( base and derived and not declarations.is_base_and_derived( @@ -258,7 +258,7 @@ def test_remove_pointer(self): def test_is_unary_binary_operator(self): operator_not = declarations.find_declaration( self.declarations, - type=declarations.operator_t, + decl_type=declarations.operator_t, fullname='::is_unary_operator::dummy::operator!') self.assertTrue(operator_not, 'operator! was not found') self.assertTrue( @@ -270,7 +270,7 @@ def test_is_unary_binary_operator(self): operator_class_p = declarations.find_declaration( self.declarations, - type=declarations.operator_t, + decl_type=declarations.operator_t, fullname='::is_unary_operator::dummy::operator+') self.assertTrue(operator_class_p, 'operator+ was not found') self.assertTrue( @@ -282,7 +282,7 @@ def test_is_unary_binary_operator(self): operator_class_pp = declarations.find_declaration( self.declarations, - type=declarations.operator_t, + decl_type=declarations.operator_t, fullname='::is_unary_operator::dummy::operator++') self.assertTrue(operator_class_pp, 'operator++ was not found') self.assertTrue( @@ -294,7 +294,7 @@ def test_is_unary_binary_operator(self): operator_pp = declarations.find_declaration( self.declarations, - type=declarations.operator_t, + decl_type=declarations.operator_t, fullname='::is_unary_operator::operator++') self.assertTrue(operator_pp, 'operator++ was not found') self.assertTrue( @@ -306,7 +306,7 @@ def test_is_unary_binary_operator(self): operator_mm = declarations.find_declaration( self.declarations, - type=declarations.operator_t, + decl_type=declarations.operator_t, fullname='::is_unary_operator::operator*') self.assertTrue(operator_mm, 'operator-- was not found') self.assertTrue( @@ -318,7 +318,7 @@ def test_is_unary_binary_operator(self): operator_pe = declarations.find_declaration( self.declarations, - type=declarations.operator_t, + decl_type=declarations.operator_t, fullname='::is_unary_operator::operator+=') self.assertTrue(operator_pe, 'operator+= was not found') self.assertTrue( @@ -335,7 +335,7 @@ def __is_convertible_impl(self, decl): expected_type = declarations.find_declaration( defs, name='expected', - type=declarations.enumeration_t) + decl_type=declarations.enumeration_t) expected_value = bool(expected_type.get_name2value_dict()['value']) self.assertTrue( expected_value == declarations.is_convertible( @@ -347,7 +347,7 @@ def __is_convertible_impl(self, decl): def test_is_convertible(self): ns_is_convertible = declarations.find_declaration( self.declarations, - type=declarations.namespace_t, + decl_type=declarations.namespace_t, name="is_convertible") self.assertTrue( @@ -390,7 +390,7 @@ def test(self): # def test( self ): # x = declarations.find_declaration( self.declarations - # , type=declarations.typedef_t + # , decl_type=declarations.typedef_t # , name="s2s_multimap_type" ) # print declarations.is_noncopyable( x) # declarations.print_declarations( diff --git a/unittests/typedefs_tester.py b/unittests/typedefs_tester.py index 2d751160..1550eed7 100644 --- a/unittests/typedefs_tester.py +++ b/unittests/typedefs_tester.py @@ -24,7 +24,7 @@ def setUp(self): self.declarations = parser.parse([self.header], self.config) self.global_ns = declarations.find_declaration( self.declarations, - type=declarations.namespace_t, + decl_type=declarations.namespace_t, name='::') self.global_ns.init_optimizer() @@ -54,7 +54,7 @@ def setUp(self): def test(self): item_cls = declarations.find_declaration( self.declarations, - type=declarations.class_t, + decl_type=declarations.class_t, name='item_t') self.assertTrue(item_cls, "unable to find class 'item_t'") self.assertTrue(len(item_cls.aliases) == 3) From b0a0ca6c515a5a402cea3bbea61141a59884179d Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 29 May 2016 14:00:07 +0200 Subject: [PATCH 148/268] Deprecate type argument intargument_t class decl_type should be used instead. The type argument will be removed in version 1.9.0 --- pygccxml/declarations/calldef.py | 33 +++++++++++++++++++++++--------- pygccxml/parser/scanner.py | 2 +- unittests/declarations_tester.py | 8 ++++---- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index c27d9f32..e486cf9b 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -77,12 +77,27 @@ def __init__( self, name='', type=None, + decl_type=None, default_value=None, attributes=None): object.__init__(self) + + if type is not None: + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type + self._name = name self._default_value = default_value - self._type = type + self._decl_type = decl_type self._attributes = attributes def clone(self, **keywd): @@ -90,15 +105,15 @@ def clone(self, **keywd): return argument_t( name=keywd.get('name', self.name), - type=keywd.get('type', self.decl_type), + decl_type=keywd.get('decl_type', self.decl_type), default_value=keywd.get('default_value', self.default_value), attributes=keywd.get('attributes', self.attributes )) """ return argument_t( name=keywd.get( - 'name', self.name), type=keywd.get( - 'type', self.decl_type), default_value=keywd.get( + 'name', self.name), decl_type=keywd.get( + 'decl_type', self.decl_type), default_value=keywd.get( 'default_value', self.default_value), attributes=keywd.get( 'attributes', self.attributes)) @@ -171,10 +186,10 @@ def type(self): warnings.warn( "argument_t.type is deprecated.\n" + "Please use argument_t.decl_type instead.", DeprecationWarning) - return self._type + return self._decl_type @type.setter - def type(self, _type): + def type(self, _decl_type): """ Deprecated since v1.8.0. Will be removed in v1.9.0 @@ -183,15 +198,15 @@ def type(self, _type): warnings.warn( "argument_t.type is deprecated.\n" + "Please use argument_t.decl_type instead.", DeprecationWarning) - self._type = _type + self._decl_type = _decl_type @property def decl_type(self): - return self._type + return self._decl_type @decl_type.setter def decl_type(self, decl_type): - self._type = decl_type + self._decl_type = decl_type @property def attributes(self): diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index 75822754..6cc603a5 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -464,7 +464,7 @@ def __read_ellipsis(self, attrs): if isinstance(self.__inst, declarations.calldef_type_t): self.__inst.arguments_types.append('...') else: - argument = declarations.argument_t(type='...') + argument = declarations.argument_t(decl_type='...') self.__inst.arguments.append(argument) def __read_calldef(self, calldef, attrs, is_declaration): diff --git a/unittests/declarations_tester.py b/unittests/declarations_tester.py index 6ffc4704..a4bdcc43 100644 --- a/unittests/declarations_tester.py +++ b/unittests/declarations_tester.py @@ -114,7 +114,7 @@ def test_calldef_free_functions(self): no_return_1_arg, [declarations.argument_t( name=no_return_1_arg.arguments[0].name, - type=declarations.int_t())]) + decl_type=declarations.int_t())]) return_default_args = ns.free_function('return_default_args') self.assertTrue( @@ -125,11 +125,11 @@ def test_calldef_free_functions(self): return_default_args, [declarations.argument_t( name=return_default_args.arguments[0].name, - type=declarations.int_t(), + decl_type=declarations.int_t(), default_value='1'), declarations.argument_t( name=return_default_args.arguments[1].name, - type=declarations.bool_t(), + decl_type=declarations.bool_t(), default_value='false')]) self._test_calldef_exceptions(return_default_args, []) @@ -150,7 +150,7 @@ def test_calldef_member_functions(self): self._test_calldef_args( member_inline_call, [ declarations.argument_t( - name='i', type=declarations.int_t())]) + name='i', decl_type=declarations.int_t())]) member_const_call = struct_calldefs.member_function( 'member_const_call') From 5d7439a6a17c30fbddb2a5007ec6be080852585e Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 29 May 2016 23:36:01 +0200 Subject: [PATCH 149/268] Move the free_calldef_t class (and subclasses) to separate module This makes the calldef module shorter, and breaks a cyclic import dependency (type_traits). --- docs/examples/searching1/example.py | 2 +- pygccxml/declarations/__init__.py | 7 +- pygccxml/declarations/calldef.py | 102 ------------------------ pygccxml/declarations/decl_factory.py | 4 +- pygccxml/declarations/free_calldef.py | 109 ++++++++++++++++++++++++++ 5 files changed, 116 insertions(+), 108 deletions(-) create mode 100644 pygccxml/declarations/free_calldef.py diff --git a/docs/examples/searching1/example.py b/docs/examples/searching1/example.py index f80a0278..6c87fab5 100644 --- a/docs/examples/searching1/example.py +++ b/docs/examples/searching1/example.py @@ -49,7 +49,7 @@ for decl in ns_namespace.declarations: if decl.name == "b": print(decl) - if isinstance(decl, declarations.calldef.free_function_t): + if isinstance(decl, declarations.free_function_t): print(decl) # This prints: diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index f88f6473..a53804f4 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -99,15 +99,16 @@ from .calldef import argument_t from .calldef import calldef_t from .calldef import member_calldef_t -from .calldef import free_calldef_t from .calldef import operator_t from .calldef import member_function_t from .calldef import constructor_t from .calldef import destructor_t from .calldef import member_operator_t from .calldef import casting_operator_t -from .calldef import free_function_t -from .calldef import free_operator_t + +from .free_calldef import free_calldef_t +from .free_calldef import free_function_t +from .free_calldef import free_operator_t from .decl_visitor import decl_visitor_t from .type_visitor import type_visitor_t diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index e486cf9b..a56bd7de 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -662,59 +662,6 @@ def guess_calling_convention(self): return CALLING_CONVENTION_TYPES.THISCALL -class free_calldef_t(calldef_t): - - """base class for "callable" declarations that defined within - C++ namespace""" - - def __init__(self, *args, **keywords): - calldef_t.__init__(self, *args, **keywords) - - def __str__(self): - # Get the full name of the calldef... - name = algorithm.full_name(self) - if name[:2] == "::": - name = name[2:] - # Add the arguments... - args = [str(a) for a in self.arguments] - res = "%s(%s)" % (name, ", ".join(args)) - # Add the return type... - if self.return_type is not None: - res = "%s %s" % (self.return_type, res) - # extern? - if self.has_extern: - res = "extern " + res - # Append the declaration class - cls = self.__class__.__name__ - if cls[-2:] == "_t": - cls = cls[:-2] - cls = cls.replace('_', ' ') - return "%s [%s]" % (res, cls) - - def _get__cmp__call_items(self): - """implementation details""" - return [] - - def function_type(self): - """returns function type. See :class:`type_t` hierarchy""" - return cpptypes.free_function_type_t( - return_type=self.return_type, - arguments_types=[ - arg.decl_type for arg in self.arguments]) - - def create_decl_string(self, with_defaults=True): - f_type = self.function_type() - if with_defaults: - return f_type.decl_string - else: - return f_type.partial_decl_string - - def guess_calling_convention(self): - """This function should be overriden in the derived classes and return - more-or-less successfull guess about calling convention""" - return CALLING_CONVENTION_TYPES.UNKNOWN - - class operator_t(object): """base class for "operator" declarations""" @@ -855,52 +802,3 @@ class casting_operator_t(member_calldef_t, operator_t): def __init__(self, *args, **keywords): member_calldef_t.__init__(self, *args, **keywords) operator_t.__init__(self, *args, **keywords) - - -class free_function_t(free_calldef_t): - - """describes free function declaration""" - - def __init__(self, *args, **keywords): - free_calldef_t.__init__(self, *args, **keywords) - - def get_mangled_name(self): - if not self._mangled and not self._demangled \ - and '<' not in self.name and not self.overloads: - # it is possible we deal with C function, so lets put it name as - # mangled one - return self.name - else: - return self._mangled - - -class free_operator_t(free_calldef_t, operator_t): - - """describes free operator declaration""" - - def __init__(self, *args, **keywords): - free_calldef_t.__init__(self, *args, **keywords) - operator_t.__init__(self, *args, **keywords) - self.__class_types = None - - @property - def class_types(self): - """list of class/class declaration types, extracted from the - operator arguments""" - - from . import type_traits - if None is self.__class_types: - self.__class_types = [] - for type_ in self.argument_types: - decl = None - type_ = type_traits.remove_reference(type_) - if type_traits.is_class(type_): - decl = type_traits.class_traits.get_declaration(type_) - elif type_traits.is_class_declaration(type_): - tt = type_traits.class_declaration_traits - decl = tt.get_declaration(type_) - else: - pass - if decl: - self.__class_types.append(decl) - return self.__class_types diff --git a/pygccxml/declarations/decl_factory.py b/pygccxml/declarations/decl_factory.py index 718a0a03..03f6f9dc 100644 --- a/pygccxml/declarations/decl_factory.py +++ b/pygccxml/declarations/decl_factory.py @@ -12,8 +12,8 @@ from .calldef import destructor_t from .calldef import member_operator_t from .calldef import casting_operator_t -from .calldef import free_function_t -from .calldef import free_operator_t +from .free_calldef import free_function_t +from .free_calldef import free_operator_t from .enumeration import enumeration_t from .namespace import namespace_t from .class_declaration import class_t diff --git a/pygccxml/declarations/free_calldef.py b/pygccxml/declarations/free_calldef.py new file mode 100644 index 00000000..07e99ccc --- /dev/null +++ b/pygccxml/declarations/free_calldef.py @@ -0,0 +1,109 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +from . import calldef +from . import algorithm +from . import cpptypes +from . import type_traits + + +class free_calldef_t(calldef.calldef_t): + + """base class for "callable" declarations that defined within + C++ namespace""" + + def __init__(self, *args, **keywords): + calldef.calldef_t.__init__(self, *args, **keywords) + + def __str__(self): + # Get the full name of the calldef... + name = algorithm.full_name(self) + if name[:2] == "::": + name = name[2:] + # Add the arguments... + args = [str(a) for a in self.arguments] + res = "%s(%s)" % (name, ", ".join(args)) + # Add the return type... + if self.return_type is not None: + res = "%s %s" % (self.return_type, res) + # extern? + if self.has_extern: + res = "extern " + res + # Append the declaration class + cls = self.__class__.__name__ + if cls[-2:] == "_t": + cls = cls[:-2] + cls = cls.replace('_', ' ') + return "%s [%s]" % (res, cls) + + def _get__cmp__call_items(self): + """implementation details""" + return [] + + def function_type(self): + """returns function type. See :class:`type_t` hierarchy""" + return cpptypes.free_function_type_t( + return_type=self.return_type, + arguments_types=[ + arg.decl_type for arg in self.arguments]) + + def create_decl_string(self, with_defaults=True): + f_type = self.function_type() + if with_defaults: + return f_type.decl_string + else: + return f_type.partial_decl_string + + def guess_calling_convention(self): + """This function should be overriden in the derived classes and return + more-or-less successfull guess about calling convention""" + return calldef.CALLING_CONVENTION_TYPES.UNKNOWN + + +class free_function_t(free_calldef_t): + + """describes free function declaration""" + + def __init__(self, *args, **keywords): + free_calldef_t.__init__(self, *args, **keywords) + + def get_mangled_name(self): + if not self._mangled and not self._demangled \ + and '<' not in self.name and not self.overloads: + # it is possible we deal with C function, so lets put it name as + # mangled one + return self.name + else: + return self._mangled + + +class free_operator_t(free_calldef_t, calldef.operator_t): + + """describes free operator declaration""" + + def __init__(self, *args, **keywords): + free_calldef_t.__init__(self, *args, **keywords) + calldef.operator_t.__init__(self, *args, **keywords) + self.__class_types = None + + @property + def class_types(self): + """list of class/class declaration types, extracted from the + operator arguments""" + + if None is self.__class_types: + self.__class_types = [] + for type_ in self.argument_types: + decl = None + type_ = type_traits.remove_reference(type_) + if type_traits.is_class(type_): + decl = type_traits.class_traits.get_declaration(type_) + elif type_traits.is_class_declaration(type_): + tt = type_traits.class_declaration_traits + decl = tt.get_declaration(type_) + else: + pass + if decl: + self.__class_types.append(decl) + return self.__class_types From 408edfe923d57c33cbbf83fc9ab6ceedd0df5f60 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 30 May 2016 18:36:57 +0200 Subject: [PATCH 150/268] Get classes directly through API in tests --- unittests/test_copy_constructor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unittests/test_copy_constructor.py b/unittests/test_copy_constructor.py index 9d687c96..558ec35c 100644 --- a/unittests/test_copy_constructor.py +++ b/unittests/test_copy_constructor.py @@ -31,7 +31,7 @@ def test(self): tclass = self.global_ns.class_("test") ctors = [] for decl in tclass.declarations: - if isinstance(decl, declarations.calldef.constructor_t): + if isinstance(decl, declarations.constructor_t): ctors.append(decl) # test::test(test const & t0) [copy constructor] @@ -44,7 +44,7 @@ def test(self): t2class = self.global_ns.class_("test2") ctors = [] for decl in t2class.declarations: - if isinstance(decl, declarations.calldef.constructor_t): + if isinstance(decl, declarations.constructor_t): ctors.append(decl) # GCCXML and CastXML return the constructors in a different order. From 8ec2ac63bbc29364d8ebde40628bbf44af5b5c5d Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 30 May 2016 18:53:29 +0200 Subject: [PATCH 151/268] Move the called member classes to a new module This makes the calldef module shorter --- pygccxml/declarations/__init__.py | 14 +- pygccxml/declarations/calldef.py | 262 -------------------- pygccxml/declarations/calldef_members.py | 269 +++++++++++++++++++++ pygccxml/declarations/class_declaration.py | 3 +- pygccxml/declarations/decl_factory.py | 10 +- pygccxml/declarations/decl_printer.py | 3 +- pygccxml/declarations/free_calldef.py | 6 +- pygccxml/declarations/function_traits.py | 5 +- pygccxml/declarations/matchers.py | 3 +- pygccxml/declarations/type_traits.py | 18 +- 10 files changed, 303 insertions(+), 290 deletions(-) create mode 100644 pygccxml/declarations/calldef_members.py diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index a53804f4..ea367d41 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -98,13 +98,13 @@ from .calldef import CALLING_CONVENTION_TYPES from .calldef import argument_t from .calldef import calldef_t -from .calldef import member_calldef_t -from .calldef import operator_t -from .calldef import member_function_t -from .calldef import constructor_t -from .calldef import destructor_t -from .calldef import member_operator_t -from .calldef import casting_operator_t +from .calldef_members import member_calldef_t +from .calldef_members import operator_t +from .calldef_members import member_function_t +from .calldef_members import constructor_t +from .calldef_members import destructor_t +from .calldef_members import member_operator_t +from .calldef_members import casting_operator_t from .free_calldef import free_calldef_t from .free_calldef import free_function_t diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index a56bd7de..a0e132a3 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -540,265 +540,3 @@ def mangled(self): @mangled.setter def mangled(self, mangled): self._mangled = mangled - - -# Second level in hierarchy of calldef -class member_calldef_t(calldef_t): - - """base class for "callable" declarations that defined within - C++ class or struct""" - - def __init__( - self, - virtuality=None, - has_const=None, - has_static=None, - *args, - **keywords): - calldef_t.__init__(self, *args, **keywords) - self._virtuality = virtuality - self._has_const = has_const - self._has_static = has_static - - def __str__(self): - # Get the full name of the calldef... - name = algorithm.full_name(self) - if name[:2] == "::": - name = name[2:] - # Add the arguments... - args = [str(a) for a in self.arguments] - res = "%s(%s)" % (name, ", ".join(args)) - # Add the return type... - if self.return_type is not None: - res = "%s %s" % (self.return_type, res) - # const? - if self.has_const: - res += " const" - # static? - if self.has_static: - res = "static " + res - # Append the declaration class - cls = self.__class__.__name__ - if cls[-2:] == "_t": - cls = cls[:-2] - cls = cls.replace('_', ' ') - return "%s [%s]" % (res, cls) - - def _get__cmp__call_items(self): - """implementation details""" - return [self.virtuality, self.has_static, self.has_const] - - def __eq__(self, other): - if not calldef_t.__eq__(self, other): - return False - return self.virtuality == other.virtuality \ - and self.has_static == other.has_static \ - and self.has_const == other.has_const - - def __hash__(self): - return super.__hash__(self) - - @property - def virtuality(self): - """Describes the "virtuality" of the member (as defined by the - string constants in the class :class:VIRTUALITY_TYPES). - @type: str""" - return self._virtuality - - @virtuality.setter - def virtuality(self, virtuality): - assert virtuality in VIRTUALITY_TYPES.ALL - self._virtuality = virtuality - - @property - def access_type(self): - """Return the access type of the member (as defined by the - string constants in the class :class:ACCESS_TYPES. - @type: str""" - return self.parent.find_out_member_access_type(self) - - @property - def has_const(self): - """describes, whether "callable" has const modifier or not""" - return self._has_const - - @has_const.setter - def has_const(self, has_const): - self._has_const = has_const - - @property - def has_static(self): - """describes, whether "callable" has static modifier or not""" - return self._has_static - - @has_static.setter - def has_static(self, has_static): - self._has_static = has_static - - def function_type(self): - """returns function type. See :class:`type_t` hierarchy""" - if self.has_static: - return cpptypes.free_function_type_t( - return_type=self.return_type, - arguments_types=[arg.decl_type for arg in self.arguments]) - else: - return cpptypes.member_function_type_t( - class_inst=self.parent, - return_type=self.return_type, - arguments_types=[arg.decl_type for arg in self.arguments], - has_const=self.has_const) - - def create_decl_string(self, with_defaults=True): - f_type = self.function_type() - if with_defaults: - return f_type.decl_string - else: - return f_type.partial_decl_string - - def guess_calling_convention(self): - if self.has_static: - return CALLING_CONVENTION_TYPES.SYSTEM_DEFAULT - else: - return CALLING_CONVENTION_TYPES.THISCALL - - -class operator_t(object): - - """base class for "operator" declarations""" - OPERATOR_WORD_LEN = len('operator') - - def __init__(self): - object.__init__(self) - - @property - def symbol(self): - """operator's symbol. For example: operator+, symbol is equal to '+'""" - return self.name[operator_t.OPERATOR_WORD_LEN:].strip() - -# Third level in hierarchy of calldef - - -class member_function_t(member_calldef_t): - - """describes member function declaration""" - - def __init__(self, *args, **keywords): - member_calldef_t.__init__(self, *args, **keywords) - - -class constructor_t(member_calldef_t): - - """describes constructor declaration""" - - def __init__(self, *args, **keywords): - member_calldef_t.__init__(self, *args, **keywords) - self._explicit = True - - @property - def explicit(self): - """True, if constructor has "explicit" keyword, False otherwise - @type: bool""" - return self._explicit - - @explicit.setter - def explicit(self, explicit): - if explicit in [True, '1']: - self._explicit = True - else: - self._explicit = False - - def __str__(self): - # Get the full name of the calldef... - name = algorithm.full_name(self) - if name[:2] == "::": - name = name[2:] - # Add the arguments... - args = [str(a) for a in self.arguments] - res = "%s(%s)" % (name, ", ".join(args)) - # Append the declaration class - cls = 'constructor' - if self.is_copy_constructor: - cls = 'copy ' + cls - return "%s [%s]" % (res, cls) - - @property - def is_copy_constructor(self): - """ - Returns True if described declaration is copy constructor, - otherwise False. - - """ - - from . import type_traits - - args = self.arguments - - # A copy constructor has only one argument - if len(args) != 1: - return False - - # We have only one argument, get it - arg = args[0] - - if not isinstance(arg.decl_type, cpptypes.compound_t): - # An argument of type declarated_t (a typedef) could be passed to - # the constructor; and it could be a reference. - # But in c++ you can NOT write : - # "typedef class MyClass { MyClass(const MyClass & arg) {} }" - # If the argument is a typedef, this is not a copy constructor. - # See the hierarchy of declarated_t and coumpound_t. They both - # inherit from type_t but are not related so we can discriminate - # between them. - return False - - # The argument needs to be passed by reference in a copy constructor - if not type_traits.is_reference(arg.decl_type): - return False - - # The argument needs to be const for a copy constructor - if not type_traits.is_const(arg.decl_type.base): - return False - - un_aliased = type_traits.remove_alias(arg.decl_type.base) - # un_aliased now refers to const_t instance - if not isinstance(un_aliased.base, cpptypes.declarated_t): - # We are looking for a declaration - # If "class MyClass { MyClass(const int & arg) {} }" is used, - # this is not copy constructor, so we return False here. - # -> un_aliased.base == cpptypes.int_t (!= cpptypes.declarated_t) - return False - - # Final check: compare the parent (the class declaration for example) - # with the declaration of the type passed as argument. - return id(un_aliased.base.declaration) == id(self.parent) - - @property - def is_trivial_constructor(self): - return not bool(self.arguments) - - -class destructor_t(member_calldef_t): - - """describes deconstructor declaration""" - - def __init__(self, *args, **keywords): - member_calldef_t.__init__(self, *args, **keywords) - - -class member_operator_t(member_calldef_t, operator_t): - - """describes member operator declaration""" - - def __init__(self, *args, **keywords): - member_calldef_t.__init__(self, *args, **keywords) - operator_t.__init__(self, *args, **keywords) - self.__class_types = None - - -class casting_operator_t(member_calldef_t, operator_t): - - """describes casting operator declaration""" - - def __init__(self, *args, **keywords): - member_calldef_t.__init__(self, *args, **keywords) - operator_t.__init__(self, *args, **keywords) diff --git a/pygccxml/declarations/calldef_members.py b/pygccxml/declarations/calldef_members.py new file mode 100644 index 00000000..0ef24057 --- /dev/null +++ b/pygccxml/declarations/calldef_members.py @@ -0,0 +1,269 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +from . import calldef +from . import algorithm +from . import cpptypes + + +# Second level in hierarchy of calldef +class member_calldef_t(calldef.calldef_t): + + """base class for "callable" declarations that defined within + C++ class or struct""" + + def __init__( + self, + virtuality=None, + has_const=None, + has_static=None, + *args, + **keywords): + calldef.calldef_t.__init__(self, *args, **keywords) + self._virtuality = virtuality + self._has_const = has_const + self._has_static = has_static + + def __str__(self): + # Get the full name of the calldef... + name = algorithm.full_name(self) + if name[:2] == "::": + name = name[2:] + # Add the arguments... + args = [str(a) for a in self.arguments] + res = "%s(%s)" % (name, ", ".join(args)) + # Add the return type... + if self.return_type is not None: + res = "%s %s" % (self.return_type, res) + # const? + if self.has_const: + res += " const" + # static? + if self.has_static: + res = "static " + res + # Append the declaration class + cls = self.__class__.__name__ + if cls[-2:] == "_t": + cls = cls[:-2] + cls = cls.replace('_', ' ') + return "%s [%s]" % (res, cls) + + def _get__cmp__call_items(self): + """implementation details""" + return [self.virtuality, self.has_static, self.has_const] + + def __eq__(self, other): + if not calldef.calldef_t.__eq__(self, other): + return False + return self.virtuality == other.virtuality \ + and self.has_static == other.has_static \ + and self.has_const == other.has_const + + def __hash__(self): + return super.__hash__(self) + + @property + def virtuality(self): + """Describes the "virtuality" of the member (as defined by the + string constants in the class :class:VIRTUALITY_TYPES). + @type: str""" + return self._virtuality + + @virtuality.setter + def virtuality(self, virtuality): + assert virtuality in calldef.VIRTUALITY_TYPES.ALL + self._virtuality = virtuality + + @property + def access_type(self): + """Return the access type of the member (as defined by the + string constants in the class :class:ACCESS_TYPES. + @type: str""" + return self.parent.find_out_member_access_type(self) + + @property + def has_const(self): + """describes, whether "callable" has const modifier or not""" + return self._has_const + + @has_const.setter + def has_const(self, has_const): + self._has_const = has_const + + @property + def has_static(self): + """describes, whether "callable" has static modifier or not""" + return self._has_static + + @has_static.setter + def has_static(self, has_static): + self._has_static = has_static + + def function_type(self): + """returns function type. See :class:`type_t` hierarchy""" + if self.has_static: + return cpptypes.free_function_type_t( + return_type=self.return_type, + arguments_types=[arg.decl_type for arg in self.arguments]) + else: + return cpptypes.member_function_type_t( + class_inst=self.parent, + return_type=self.return_type, + arguments_types=[arg.decl_type for arg in self.arguments], + has_const=self.has_const) + + def create_decl_string(self, with_defaults=True): + f_type = self.function_type() + if with_defaults: + return f_type.decl_string + else: + return f_type.partial_decl_string + + def guess_calling_convention(self): + if self.has_static: + return calldef.CALLING_CONVENTION_TYPES.SYSTEM_DEFAULT + else: + return calldef.CALLING_CONVENTION_TYPES.THISCALL + + +class operator_t(object): + + """base class for "operator" declarations""" + OPERATOR_WORD_LEN = len('operator') + + def __init__(self): + object.__init__(self) + + @property + def symbol(self): + """operator's symbol. For example: operator+, symbol is equal to '+'""" + return self.name[operator_t.OPERATOR_WORD_LEN:].strip() + + +# Third level in hierarchy of calldef +class member_function_t(member_calldef_t): + + """describes member function declaration""" + + def __init__(self, *args, **keywords): + member_calldef_t.__init__(self, *args, **keywords) + + +class constructor_t(member_calldef_t): + + """describes constructor declaration""" + + def __init__(self, *args, **keywords): + member_calldef_t.__init__(self, *args, **keywords) + self._explicit = True + + @property + def explicit(self): + """True, if constructor has "explicit" keyword, False otherwise + @type: bool""" + return self._explicit + + @explicit.setter + def explicit(self, explicit): + if explicit in [True, '1']: + self._explicit = True + else: + self._explicit = False + + def __str__(self): + # Get the full name of the calldef... + name = algorithm.full_name(self) + if name[:2] == "::": + name = name[2:] + # Add the arguments... + args = [str(a) for a in self.arguments] + res = "%s(%s)" % (name, ", ".join(args)) + # Append the declaration class + cls = 'constructor' + if self.is_copy_constructor: + cls = 'copy ' + cls + return "%s [%s]" % (res, cls) + + @property + def is_copy_constructor(self): + """ + Returns True if described declaration is copy constructor, + otherwise False. + + """ + + from . import type_traits + + args = self.arguments + + # A copy constructor has only one argument + if len(args) != 1: + return False + + # We have only one argument, get it + arg = args[0] + + if not isinstance(arg.decl_type, cpptypes.compound_t): + # An argument of type declarated_t (a typedef) could be passed to + # the constructor; and it could be a reference. + # But in c++ you can NOT write : + # "typedef class MyClass { MyClass(const MyClass & arg) {} }" + # If the argument is a typedef, this is not a copy constructor. + # See the hierarchy of declarated_t and coumpound_t. They both + # inherit from type_t but are not related so we can discriminate + # between them. + return False + + # The argument needs to be passed by reference in a copy constructor + if not type_traits.is_reference(arg.decl_type): + return False + + # The argument needs to be const for a copy constructor + if not type_traits.is_const(arg.decl_type.base): + return False + + un_aliased = type_traits.remove_alias(arg.decl_type.base) + # un_aliased now refers to const_t instance + if not isinstance(un_aliased.base, cpptypes.declarated_t): + # We are looking for a declaration + # If "class MyClass { MyClass(const int & arg) {} }" is used, + # this is not copy constructor, so we return False here. + # -> un_aliased.base == cpptypes.int_t (!= cpptypes.declarated_t) + return False + + # Final check: compare the parent (the class declaration for example) + # with the declaration of the type passed as argument. + return id(un_aliased.base.declaration) == id(self.parent) + + @property + def is_trivial_constructor(self): + return not bool(self.arguments) + + +class destructor_t(member_calldef_t): + + """describes deconstructor declaration""" + + def __init__(self, *args, **keywords): + member_calldef_t.__init__(self, *args, **keywords) + + +class member_operator_t(member_calldef_t, operator_t): + + """describes member operator declaration""" + + def __init__(self, *args, **keywords): + member_calldef_t.__init__(self, *args, **keywords) + operator_t.__init__(self, *args, **keywords) + self.__class_types = None + + +class casting_operator_t(member_calldef_t, operator_t): + + """describes casting operator declaration""" + + def __init__(self, *args, **keywords): + member_calldef_t.__init__(self, *args, **keywords) + operator_t.__init__(self, *args, **keywords) diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 1fed376c..6dd5abe8 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -632,9 +632,10 @@ def find_noncopyable_vars(self): def has_vtable(self): """True, if class has virtual table, False otherwise""" from . import calldef + from . import calldef_members return bool( self.calldefs( - lambda f: isinstance(f, calldef.member_function_t) and + lambda f: isinstance(f, calldef_members.member_function_t) and f.virtuality != calldef.VIRTUALITY_TYPES.NOT_VIRTUAL, recursive=False, allow_empty=True)) diff --git a/pygccxml/declarations/decl_factory.py b/pygccxml/declarations/decl_factory.py index 03f6f9dc..c745de9e 100644 --- a/pygccxml/declarations/decl_factory.py +++ b/pygccxml/declarations/decl_factory.py @@ -7,11 +7,11 @@ defines default declarations factory class """ -from .calldef import member_function_t -from .calldef import constructor_t -from .calldef import destructor_t -from .calldef import member_operator_t -from .calldef import casting_operator_t +from .calldef_members import member_function_t +from .calldef_members import constructor_t +from .calldef_members import destructor_t +from .calldef_members import member_operator_t +from .calldef_members import casting_operator_t from .free_calldef import free_function_t from .free_calldef import free_operator_t from .enumeration import enumeration_t diff --git a/pygccxml/declarations/decl_printer.py b/pygccxml/declarations/decl_printer.py index 34d7185d..1c657039 100644 --- a/pygccxml/declarations/decl_printer.py +++ b/pygccxml/declarations/decl_printer.py @@ -11,6 +11,7 @@ import os import sys from . import calldef +from . import calldef_members from . import algorithm from . import decl_visitor from . import variable_t @@ -212,7 +213,7 @@ def print_calldef_info(self, decl=None): "calling convention: __%s__" % decl.calling_convention + os.linesep) - if isinstance(decl, calldef.member_calldef_t): + if isinstance(decl, calldef_members.member_calldef_t): self.writer(indent + "virtual: " + str(decl.virtuality) + diff --git a/pygccxml/declarations/free_calldef.py b/pygccxml/declarations/free_calldef.py index 07e99ccc..c6b9c6fc 100644 --- a/pygccxml/declarations/free_calldef.py +++ b/pygccxml/declarations/free_calldef.py @@ -1,8 +1,10 @@ # Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt from . import calldef +from . import calldef_members from . import algorithm from . import cpptypes from . import type_traits @@ -78,13 +80,13 @@ def get_mangled_name(self): return self._mangled -class free_operator_t(free_calldef_t, calldef.operator_t): +class free_operator_t(free_calldef_t, calldef_members.operator_t): """describes free operator declaration""" def __init__(self, *args, **keywords): free_calldef_t.__init__(self, *args, **keywords) - calldef.operator_t.__init__(self, *args, **keywords) + calldef_members.operator_t.__init__(self, *args, **keywords) self.__class_types = None @property diff --git a/pygccxml/declarations/function_traits.py b/pygccxml/declarations/function_traits.py index ba7fa739..203d724e 100644 --- a/pygccxml/declarations/function_traits.py +++ b/pygccxml/declarations/function_traits.py @@ -8,6 +8,7 @@ """ from . import calldef +from . import calldef_members from . import type_traits @@ -30,7 +31,7 @@ def is_same_return_type(f1, f2): if f1.__class__ is not f2.__class__: # it should be assert return False # 2 different calldef types - if not isinstance(f1, calldef.member_calldef_t): + if not isinstance(f1, calldef_members.member_calldef_t): # for free functions we compare return types as usual return type_traits.is_same(f1.return_type, f2.return_type) if f1.virtuality == calldef.VIRTUALITY_TYPES.NOT_VIRTUAL \ @@ -77,7 +78,7 @@ def is_same_function(f1, f2): return True if f1.__class__ is not f2.__class__: return False - if isinstance(f1, calldef.member_calldef_t) and \ + if isinstance(f1, calldef_members.member_calldef_t) and \ f1.has_const != f2.has_const: return False if f1.name != f2.name: diff --git a/pygccxml/declarations/matchers.py b/pygccxml/declarations/matchers.py index 387190e7..18eaa5da 100644 --- a/pygccxml/declarations/matchers.py +++ b/pygccxml/declarations/matchers.py @@ -15,6 +15,7 @@ from . import variable from . import namespace from . import calldef +from . import calldef_members from . import cpptypes from . import templates from . import class_declaration @@ -498,7 +499,7 @@ def __init__( :type symbol: str """ if None is decl_type: - decl_type = calldef.operator_t + decl_type = calldef_members.operator_t calldef_matcher_t.__init__( self, name=name, diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 4519ccc6..5d10b96d 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -23,6 +23,7 @@ from . import matchers from . import typedef from . import calldef +from . import calldef_members from . import cpptypes from . import algorithm from . import namespace @@ -502,7 +503,7 @@ def has_destructor(class_): None otherwise""" class_ = class_traits.get_declaration(class_) destructor = class_.decls( - decl_type=calldef.destructor_t, + decl_type=calldef_members.destructor_t, recursive=False, allow_empty=True) if destructor: @@ -632,11 +633,11 @@ def is_unary_operator(oper): # ret-type operator symbol( arg ) # ret-type operator [++ --](X&, int) symbols = ['!', '&', '~', '*', '+', '++', '-', '--'] - if not isinstance(oper, calldef.operator_t): + if not isinstance(oper, calldef_members.operator_t): return False if oper.symbol not in symbols: return False - if isinstance(oper, calldef.member_operator_t): + if isinstance(oper, calldef_members.member_operator_t): if 0 == len(oper.arguments): return True elif oper.symbol in ['++', '--'] and \ @@ -668,11 +669,11 @@ def is_binary_operator(oper): ',', '()', '[]', '!=', '%', '%=', '&', '&&', '&=', '*', '*=', '+', '+=', '-', '-=', '->', '->*', '/', '/=', '<', '<<', '<<=', '<=', '=', '==', '>', '>=', '>>', '>>=', '^', '^=', '|', '|=', '||'] - if not isinstance(oper, calldef.operator_t): + if not isinstance(oper, calldef_members.operator_t): return False if oper.symbol not in symbols: return False - if isinstance(oper, calldef.member_operator_t): + if isinstance(oper, calldef_members.member_operator_t): if 1 == len(oper.arguments): return True else: @@ -950,7 +951,7 @@ def is_convertible(self): # has operator casting_operators = algorithm.find_all_declarations( source_inst.declarations, - decl_type=calldef.casting_operator_t, + decl_type=calldef_members.casting_operator_t, recursive=False) if casting_operators: for operator in casting_operators: @@ -963,7 +964,7 @@ def is_convertible(self): if isinstance(target.declaration, class_declaration.class_t): constructors = algorithm.find_all_declarations( target.declaration.declarations, - decl_type=calldef.constructor_t, + decl_type=calldef_members.constructor_t, recursive=False) if constructors: for constructor in constructors: @@ -1141,8 +1142,7 @@ def find_value_type(global_ns, value_type_str): value_type_str = '::' + value_type_str found = global_ns.decls( name=value_type_str, - function=lambda decl: not isinstance(decl, - calldef.calldef_t), + function=lambda decl: not isinstance(decl, calldef.calldef_t), allow_empty=True) if not found: no_global_ns_value_type_str = value_type_str[2:] From 2040872bbfb18190f797a9a62c26100b17db3156 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 30 May 2016 22:31:57 +0200 Subject: [PATCH 152/268] Move remove_alias method to type_traits_utils module - This removes a cyclic import in the calldef.py module. - The cyclic import in dependencies.py was already there and is not fixed with this solution --- pygccxml/declarations/__init__.py | 3 +- pygccxml/declarations/calldef.py | 6 +- pygccxml/declarations/calldef_members.py | 3 +- pygccxml/declarations/container_traits.py | 5 +- pygccxml/declarations/dependencies.py | 17 +++-- pygccxml/declarations/type_traits.py | 86 ++++++++-------------- pygccxml/declarations/type_traits_utils.py | 38 ++++++++++ 7 files changed, 86 insertions(+), 72 deletions(-) create mode 100644 pygccxml/declarations/type_traits_utils.py diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index ea367d41..725c73fa 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -158,7 +158,6 @@ from .type_traits import remove_cv from .type_traits import remove_const -from .type_traits import remove_alias from .type_traits import remove_pointer from .type_traits import remove_volatile from .type_traits import remove_reference @@ -181,6 +180,8 @@ from .type_traits import smart_pointer_traits from .type_traits import internal_type_traits +from .type_traits_utils import remove_alias + from .container_traits import list_traits from .container_traits import deque_traits from .container_traits import queue_traits diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index a0e132a3..d681f782 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -21,9 +21,9 @@ from . import cpptypes from . import algorithm from . import declaration -# from . import type_traits # moved below to fix a cyclic dependency problem from . import dependencies from . import call_invocation +from . import type_traits_utils from .. import utils @@ -436,8 +436,6 @@ def demangled_name(self): if "CastXML" in utils.xml_generator: raise Exception("Demangled name is not available with CastXML.") - from . import type_traits - if not self.demangled: self._demangled_name = '' @@ -449,7 +447,7 @@ def demangled_name(self): demangled = self.demangled if self.return_type: - return_type = type_traits.remove_alias( + return_type = type_traits_utils.remove_alias( self.return_type).decl_string if return_type.startswith('::') and not \ diff --git a/pygccxml/declarations/calldef_members.py b/pygccxml/declarations/calldef_members.py index 0ef24057..9bc59738 100644 --- a/pygccxml/declarations/calldef_members.py +++ b/pygccxml/declarations/calldef_members.py @@ -6,6 +6,7 @@ from . import calldef from . import algorithm from . import cpptypes +from . import type_traits_utils # Second level in hierarchy of calldef @@ -224,7 +225,7 @@ def is_copy_constructor(self): if not type_traits.is_const(arg.decl_type.base): return False - un_aliased = type_traits.remove_alias(arg.decl_type.base) + un_aliased = type_traits_utils.remove_alias(arg.decl_type.base) # un_aliased now refers to const_t instance if not isinstance(un_aliased.base, cpptypes.declarated_t): # We are looking for a declaration diff --git a/pygccxml/declarations/container_traits.py b/pygccxml/declarations/container_traits.py index 99d6a130..2c8e8255 100644 --- a/pygccxml/declarations/container_traits.py +++ b/pygccxml/declarations/container_traits.py @@ -12,6 +12,7 @@ from . import cpptypes from . import templates from . import type_traits +from . import type_traits_utils from . import namespace from . import class_declaration from .. import utils @@ -382,14 +383,14 @@ def get_container_or_none(self, type_): """ - type_ = type_traits.remove_alias(type_) + type_ = type_traits_utils.remove_alias(type_) type_ = type_traits.remove_cv(type_) utils.loggers.queries_engine.debug( "Container traits: cleaned up search %s" % type_) if isinstance(type_, cpptypes.declarated_t): - cls_declaration = type_traits.remove_alias(type_.declaration) + cls_declaration = type_traits_utils.remove_alias(type_.declaration) elif isinstance(type_, class_declaration.class_t): cls_declaration = type_ elif isinstance(type_, class_declaration.class_declaration_t): diff --git a/pygccxml/declarations/dependencies.py b/pygccxml/declarations/dependencies.py index b152d36e..d1eb21bb 100644 --- a/pygccxml/declarations/dependencies.py +++ b/pygccxml/declarations/dependencies.py @@ -10,19 +10,22 @@ """ from . import cpptypes +from . import declaration class impl_details(object): @staticmethod def dig_declarations(depend_on_it): - # prevent recursive import - from pygccxml import declarations - if isinstance(depend_on_it, declarations.declaration_t): + # FIXME: prevent cyclic imports + from . import type_traits + from . import type_traits_utils + + if isinstance(depend_on_it, declaration.declaration_t): return [depend_on_it] - base_type = declarations.base_type( - declarations.remove_alias(depend_on_it)) + base_type = type_traits.base_type( + type_traits_utils.remove_alias(depend_on_it)) if isinstance(base_type, cpptypes.declarated_t): return [base_type.declaration] elif isinstance(base_type, cpptypes.calldef_type_t): @@ -42,7 +45,7 @@ class dependency_info_t(object): def __init__(self, declaration, depend_on_it, access_type=None, hint=None): object.__init__(self) - # prevent recursive import + # FIXME: prevent cyclic import from . import class_declaration assert isinstance( depend_on_it, @@ -92,7 +95,7 @@ def find_out_depend_on_it_declarations(self): def i_depend_on_them(decl): """Returns set of declarations. every item in the returned set, depends on a declaration from the input""" - from . import class_declaration # prevent cyclic imports + from . import class_declaration # FIXME: prevent cyclic imports to_be_included = set() for dependency_info in decl.i_depend_on_them(): for ddecl in dependency_info.find_out_depend_on_it_declarations(): diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 5d10b96d..e0d12c9a 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -30,40 +30,10 @@ from . import templates from . import enumeration from . import class_declaration +from . import type_traits_utils from .. import utils -def __remove_alias(type_): - """implementation details""" - if isinstance(type_, typedef.typedef_t): - return __remove_alias(type_.decl_type) - if isinstance(type_, cpptypes.declarated_t) and \ - isinstance(type_.declaration, typedef.typedef_t): - return __remove_alias(type_.declaration.decl_type) - if isinstance(type_, cpptypes.compound_t): - type_.base = __remove_alias(type_.base) - return type_ - return type_ - - -def remove_alias(type_): - """returns type without typedefs""" - type_ref = None - if isinstance(type_, cpptypes.type_t): - type_ref = type_ - elif isinstance(type_, typedef.typedef_t): - type_ref = type_.decl_type - else: - pass # not a valid input, just return it - if not type_ref: - return type_ - if type_ref.cache.remove_alias: - return type_ref.cache.remove_alias - no_alias = __remove_alias(type_ref.clone()) - type_ref.cache.remove_alias = no_alias - return no_alias - - def create_cv_types(base): """implementation details""" return ( @@ -134,12 +104,14 @@ def does_match_definition(given, main, secondary): def is_bool(type_): """returns True, if type represents `bool`, False otherwise""" - return remove_alias(type_) in create_cv_types(cpptypes.bool_t()) + return type_traits_utils.remove_alias(type_) in create_cv_types( + cpptypes.bool_t()) def is_void(type): """returns True, if type represents `void`, False otherwise""" - return remove_alias(type) in create_cv_types(cpptypes.void_t()) + return type_traits_utils.remove_alias(type) in create_cv_types( + cpptypes.void_t()) def is_void_pointer(type): @@ -166,7 +138,7 @@ def is_integral(type): create_cv_types(cpptypes.int128_t()) + create_cv_types(cpptypes.uint128_t())) - return remove_alias(type) in integral_def + return type_traits_utils.remove_alias(type) in integral_def def is_floating_point(type): @@ -177,7 +149,7 @@ def is_floating_point(type): create_cv_types(cpptypes.double_t()) + create_cv_types(cpptypes.long_double_t())) - return remove_alias(type) in float_def + return type_traits_utils.remove_alias(type) in float_def def is_arithmetic(type): @@ -201,7 +173,7 @@ def is_calldef_pointer(type): False otherwise""" if not is_pointer(type): return False - nake_type = remove_alias(type) + nake_type = type_traits_utils.remove_alias(type) nake_type = remove_cv(nake_type) return isinstance(nake_type, cpptypes.compound_t) \ and isinstance(nake_type.base, cpptypes.calldef_type_t) @@ -212,7 +184,7 @@ def remove_pointer(type): If type is not pointer type, it will be returned as is. """ - nake_type = remove_alias(type) + nake_type = type_traits_utils.remove_alias(type) if not is_pointer(nake_type): return type elif isinstance(nake_type, cpptypes.volatile_t) and \ @@ -235,13 +207,13 @@ def remove_pointer(type): def is_reference(type): """returns True, if type represents C++ reference type, False otherwise""" - nake_type = remove_alias(type) + nake_type = type_traits_utils.remove_alias(type) return isinstance(nake_type, cpptypes.reference_t) def is_array(type): """returns True, if type represents C++ array type, False otherwise""" - nake_type = remove_alias(type) + nake_type = type_traits_utils.remove_alias(type) nake_type = remove_reference(nake_type) nake_type = remove_cv(nake_type) return isinstance(nake_type, cpptypes.array_t) @@ -249,7 +221,7 @@ def is_array(type): def array_size(type): """returns array size""" - nake_type = remove_alias(type) + nake_type = type_traits_utils.remove_alias(type) nake_type = remove_reference(nake_type) nake_type = remove_cv(nake_type) assert isinstance(nake_type, cpptypes.array_t) @@ -259,7 +231,7 @@ def array_size(type): def array_item_type(type_): """returns array item type""" if is_array(type_): - type_ = remove_alias(type_) + type_ = type_traits_utils.remove_alias(type_) type_ = remove_cv(type_) return type_.base elif is_pointer(type_): @@ -275,7 +247,7 @@ def remove_reference(type): If type is not reference type, it will be returned as is. """ - nake_type = remove_alias(type) + nake_type = type_traits_utils.remove_alias(type) if not is_reference(nake_type): return type else: @@ -284,7 +256,7 @@ def remove_reference(type): def is_const(type): """returns True, if type represents C++ const type, False otherwise""" - nake_type = remove_alias(type) + nake_type = type_traits_utils.remove_alias(type) if isinstance(nake_type, cpptypes.const_t): return True elif isinstance(nake_type, cpptypes.volatile_t): @@ -300,7 +272,7 @@ def remove_const(type_): If type is not const type, it will be returned as is """ - nake_type = remove_alias(type_) + nake_type = type_traits_utils.remove_alias(type_) if not is_const(nake_type): return type_ else: @@ -334,7 +306,7 @@ def remove_declarated(type_): If `type_` is not :class:`declarated_t`, it will be returned as is """ - type_ = remove_alias(type_) + type_ = type_traits_utils.remove_alias(type_) if isinstance(type_, cpptypes.declarated_t): type_ = type_.declaration return type_ @@ -349,7 +321,7 @@ def is_same(type1, type2): def is_volatile(type): """returns True, if type represents C++ volatile type, False otherwise""" - nake_type = remove_alias(type) + nake_type = type_traits_utils.remove_alias(type) if isinstance(nake_type, cpptypes.volatile_t): return True elif isinstance(nake_type, cpptypes.const_t): @@ -364,7 +336,7 @@ def remove_volatile(type): If type is not volatile type, it will be returned as is """ - nake_type = remove_alias(type) + nake_type = type_traits_utils.remove_alias(type) if not is_volatile(nake_type): return type else: @@ -384,7 +356,7 @@ def remove_volatile(type): def remove_cv(type): """removes const and volatile from the type definition""" - nake_type = remove_alias(type) + nake_type = type_traits_utils.remove_alias(type) if not is_const(nake_type) and not is_volatile(nake_type): return type result = nake_type @@ -425,7 +397,7 @@ class declaration_xxx_traits(object): - find out whether a declaration is a desired one - get reference to the declaration """ - sequence = [remove_alias, remove_cv, remove_declarated] + sequence = [type_traits_utils.remove_alias, remove_cv, remove_declarated] def __init__(self, declaration_class): self.declaration_class = declaration_class @@ -570,7 +542,7 @@ def has_any_non_copyconstructor(type): def has_public_binary_operator(type_, operator_symbol): """returns True, if `type_` has public binary operator, otherwise False""" - type_ = remove_alias(type_) + type_ = type_traits_utils.remove_alias(type_) type_ = remove_cv(type_) type_ = remove_declarated(type_) assert isinstance(type_, class_declaration.class_t) @@ -701,7 +673,7 @@ def __find_class_by_class_declaration(self, class_decl): return found def __normalize(self, type_): - type_ = remove_alias(type_) + type_ = type_traits_utils.remove_alias(type_) bt_of_type = base_type(type_) if isinstance(bt_of_type, cpptypes.declarated_t) \ and isinstance(bt_of_type.declaration, @@ -1218,7 +1190,7 @@ class smart_pointer_traits(object): def is_smart_pointer(type_): """returns True, if type represents instantiation of `boost::shared_ptr` or `std::shared_ptr`, False otherwise""" - type_ = remove_alias(type_) + type_ = type_traits_utils.remove_alias(type_) type_ = remove_cv(type_) type_ = remove_declarated(type_) if not isinstance(type_, @@ -1252,7 +1224,7 @@ class auto_ptr_traits(object): def is_smart_pointer(type_): """returns True, if type represents instantiation of `boost::shared_ptr`, False otherwise""" - type_ = remove_alias(type_) + type_ = type_traits_utils.remove_alias(type_) type_ = remove_cv(type_) type_ = remove_declarated(type_) if not isinstance(type_, @@ -1306,7 +1278,7 @@ def is_std_string(type_): if utils.is_str(type_): return type_ in string_equivalences else: - type_ = remove_alias(type_) + type_ = type_traits_utils.remove_alias(type_) return remove_cv(type_).decl_string in string_equivalences @@ -1319,7 +1291,7 @@ def is_std_wstring(type_): if utils.is_str(type_): return type_ in wstring_equivalences else: - type_ = remove_alias(type_) + type_ = type_traits_utils.remove_alias(type_) return remove_cv(type_).decl_string in wstring_equivalences @@ -1332,7 +1304,7 @@ def is_std_ostream(type_): if utils.is_str(type_): return type_ in ostream_equivalences else: - type_ = remove_alias(type_) + type_ = type_traits_utils.remove_alias(type_) return remove_cv(type_).decl_string in ostream_equivalences @@ -1345,5 +1317,5 @@ def is_std_wostream(type_): if utils.is_str(type_): return type_ in wostream_equivalences else: - type_ = remove_alias(type_) + type_ = type_traits_utils.remove_alias(type_) return remove_cv(type_).decl_string in wostream_equivalences diff --git a/pygccxml/declarations/type_traits_utils.py b/pygccxml/declarations/type_traits_utils.py new file mode 100644 index 00000000..aeebaf84 --- /dev/null +++ b/pygccxml/declarations/type_traits_utils.py @@ -0,0 +1,38 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +from . import typedef +from . import cpptypes + + +def __remove_alias(type_): + """implementation details""" + if isinstance(type_, typedef.typedef_t): + return __remove_alias(type_.decl_type) + if isinstance(type_, cpptypes.declarated_t) and \ + isinstance(type_.declaration, typedef.typedef_t): + return __remove_alias(type_.declaration.decl_type) + if isinstance(type_, cpptypes.compound_t): + type_.base = __remove_alias(type_.base) + return type_ + return type_ + + +def remove_alias(type_): + """returns type without typedefs""" + type_ref = None + if isinstance(type_, cpptypes.type_t): + type_ref = type_ + elif isinstance(type_, typedef.typedef_t): + type_ref = type_.decl_type + else: + pass # not a valid input, just return it + if not type_ref: + return type_ + if type_ref.cache.remove_alias: + return type_ref.cache.remove_alias + no_alias = __remove_alias(type_ref.clone()) + type_ref.cache.remove_alias = no_alias + return no_alias From 983eb7aef6d598fb280ba4dc872c3820d69c3895 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 30 May 2016 22:49:59 +0200 Subject: [PATCH 153/268] Move more methods to type_traits_utils Removes a cyclic import in dependencies.py (though this is not completely fixed) --- pygccxml/declarations/__init__.py | 7 ++- pygccxml/declarations/dependencies.py | 3 +- pygccxml/declarations/type_traits.py | 51 +++++----------------- pygccxml/declarations/type_traits_utils.py | 29 ++++++++++++ pygccxml/parser/patcher.py | 9 ++-- 5 files changed, 49 insertions(+), 50 deletions(-) diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 725c73fa..4f9ae940 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -113,9 +113,6 @@ from .decl_visitor import decl_visitor_t from .type_visitor import type_visitor_t -from .type_traits import decompose_type -from .type_traits import decompose_class - from .type_traits import is_enum from .type_traits import enum_declaration @@ -132,7 +129,6 @@ from .type_traits import is_void from .type_traits import is_void_pointer from .type_traits import is_const -from .type_traits import base_type from .type_traits import is_array from .type_traits import is_pointer from .type_traits import is_volatile @@ -180,6 +176,9 @@ from .type_traits import smart_pointer_traits from .type_traits import internal_type_traits +from .type_traits_utils import decompose_type +from .type_traits_utils import decompose_class +from .type_traits_utils import base_type from .type_traits_utils import remove_alias from .container_traits import list_traits diff --git a/pygccxml/declarations/dependencies.py b/pygccxml/declarations/dependencies.py index d1eb21bb..85ecc934 100644 --- a/pygccxml/declarations/dependencies.py +++ b/pygccxml/declarations/dependencies.py @@ -19,12 +19,11 @@ class impl_details(object): def dig_declarations(depend_on_it): # FIXME: prevent cyclic imports - from . import type_traits from . import type_traits_utils if isinstance(depend_on_it, declaration.declaration_t): return [depend_on_it] - base_type = type_traits.base_type( + base_type = type_traits_utils.base_type( type_traits_utils.remove_alias(depend_on_it)) if isinstance(base_type, cpptypes.declarated_t): return [base_type.declaration] diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index e0d12c9a..5c6b6593 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -21,7 +21,6 @@ import os from . import matchers -from . import typedef from . import calldef from . import calldef_members from . import cpptypes @@ -45,40 +44,11 @@ def create_cv_types(base): ) -def decompose_type(tp): - """implementation details""" - # implementation of this function is important - if isinstance(tp, cpptypes.compound_t): - return [tp] + decompose_type(tp.base) - elif isinstance(tp, typedef.typedef_t): - return decompose_type(tp.decl_type) - elif isinstance(tp, cpptypes.declarated_t) and \ - isinstance(tp.declaration, typedef.typedef_t): - return decompose_type(tp.declaration.decl_type) - else: - return [tp] - - -def decompose_class(type): - """implementation details""" - types = decompose_type(type) - return [tp.__class__ for tp in types] - - -def base_type(type): - """returns base type. - - For `const int` will return `int` - """ - types = decompose_type(type) - return types[-1] - - def does_match_definition(given, main, secondary): """implementation details""" assert isinstance(secondary, tuple) assert 2 == len(secondary) # general solution could be provided - types = decompose_type(given) + types = type_traits_utils.decompose_type(given) if isinstance(types[0], main): return True elif 2 <= len(types) and \ @@ -674,12 +644,12 @@ def __find_class_by_class_declaration(self, class_decl): def __normalize(self, type_): type_ = type_traits_utils.remove_alias(type_) - bt_of_type = base_type(type_) + bt_of_type = type_traits_utils.base_type(type_) if isinstance(bt_of_type, cpptypes.declarated_t) \ and isinstance(bt_of_type.declaration, class_declaration.class_declaration_t): type_ = type_.clone() - bt_of_type = base_type(type_) + bt_of_type = type_traits_utils.base_type(type_) bt_of_type.declaration = self.__find_class_by_class_declaration( bt_of_type.declaration) return type_ @@ -710,10 +680,10 @@ def __test_trivial(self, source, target): is_same(source.base, target.base.base): return True # X& => const X& if not is_const(source) and is_array(source) and is_pointer(target): - if is_same(base_type(source), target.base): + if is_same(type_traits_utils.base_type(source), target.base): return True # X[2] => X* if is_array(source) and is_pointer(target) and is_const(target.base): - if is_same(base_type(source), target.base.base): + if is_same(type_traits_utils.base_type(source), target.base.base): return True def __test_pointer_to_func_or_mv__to__func_or_mv(self, source, target): @@ -807,10 +777,11 @@ def __test_ref_x__to__y(self, source, target): return False def __test_fundamental__to__fundamental(self, source, target): - if not is_fundamental(base_type(source)) or not \ - is_fundamental(base_type(target)): + if not is_fundamental(type_traits_utils.base_type(source)) or not \ + is_fundamental(type_traits_utils.base_type(target)): return False - if is_void(base_type(source)) or is_void(base_type(target)): + if is_void(type_traits_utils.base_type(source)) or \ + is_void(type_traits_utils.base_type(target)): return False if is_fundamental(source) and is_fundamental(target): return True @@ -832,8 +803,8 @@ def _is_both_declarated(self, x, y): isinstance(y, cpptypes.declarated_t)) def __test_derived_to_based(self, source, target): - derived = base_type(source) - base = base_type(target) + derived = type_traits_utils.base_type(source) + base = type_traits_utils.base_type(target) if not ( isinstance(derived, cpptypes.declarated_t) and isinstance(derived.declaration, class_declaration.class_t)): diff --git a/pygccxml/declarations/type_traits_utils.py b/pygccxml/declarations/type_traits_utils.py index aeebaf84..49ba5018 100644 --- a/pygccxml/declarations/type_traits_utils.py +++ b/pygccxml/declarations/type_traits_utils.py @@ -36,3 +36,32 @@ def remove_alias(type_): no_alias = __remove_alias(type_ref.clone()) type_ref.cache.remove_alias = no_alias return no_alias + + +def decompose_type(tp): + """implementation details""" + # implementation of this function is important + if isinstance(tp, cpptypes.compound_t): + return [tp] + decompose_type(tp.base) + elif isinstance(tp, typedef.typedef_t): + return decompose_type(tp.decl_type) + elif isinstance(tp, cpptypes.declarated_t) and \ + isinstance(tp.declaration, typedef.typedef_t): + return decompose_type(tp.declaration.decl_type) + else: + return [tp] + + +def decompose_class(type): + """implementation details""" + types = decompose_type(type) + return [tp.__class__ for tp in types] + + +def base_type(type): + """returns base type. + + For `const int` will return `int` + """ + types = decompose_type(type) + return types[-1] diff --git a/pygccxml/parser/patcher.py b/pygccxml/parser/patcher.py index 19fddf34..b491e5ae 100644 --- a/pygccxml/parser/patcher.py +++ b/pygccxml/parser/patcher.py @@ -4,8 +4,9 @@ # See http://www.boost.org/LICENSE_1_0.txt import re -from pygccxml import utils -from pygccxml import declarations +from .. import utils +from .. import declarations +from ..declarations import type_traits_utils class default_argument_patcher_t(object): @@ -185,7 +186,7 @@ def __is_constructor_call(self, func, arg): if not call_invocation.is_call_invocation(dv): return False name = call_invocation.name(dv) - base_type = declarations.base_type(arg.decl_type) + base_type = type_traits_utils.base_type(arg.decl_type) if not isinstance(base_type, declarations.declarated_t): return False decl = base_type.declaration @@ -199,7 +200,7 @@ def __fix_constructor_call(self, func, arg): dv = arg.default_value if not call_invocation.is_call_invocation(dv): return False - base_type = declarations.base_type(arg.decl_type) + base_type = type_traits_utils.base_type(arg.decl_type) decl = base_type.declaration name, args = call_invocation.split(dv) if decl.name != name: From 5ded30d7eaa87862e45a42e08270d35bcc471d96 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 30 May 2016 23:01:35 +0200 Subject: [PATCH 154/268] Move the is_copy_constructor method the type_traits module All the other is_sth methods are there, so this is currently the right place for it --- pygccxml/declarations/__init__.py | 1 + pygccxml/declarations/calldef_members.py | 43 +--------------------- pygccxml/declarations/type_traits.py | 47 ++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 41 deletions(-) diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 4f9ae940..1286aa28 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -145,6 +145,7 @@ from .type_traits import is_std_ostream from .type_traits import is_std_wostream from .type_traits import is_calldef_pointer +from .type_traits import is_copy_constructor from .type_traits import is_unary_operator from .type_traits import is_binary_operator diff --git a/pygccxml/declarations/calldef_members.py b/pygccxml/declarations/calldef_members.py index 9bc59738..025b9165 100644 --- a/pygccxml/declarations/calldef_members.py +++ b/pygccxml/declarations/calldef_members.py @@ -195,48 +195,9 @@ def is_copy_constructor(self): """ + # FIXME: prevent cyclic dependencies from . import type_traits - - args = self.arguments - - # A copy constructor has only one argument - if len(args) != 1: - return False - - # We have only one argument, get it - arg = args[0] - - if not isinstance(arg.decl_type, cpptypes.compound_t): - # An argument of type declarated_t (a typedef) could be passed to - # the constructor; and it could be a reference. - # But in c++ you can NOT write : - # "typedef class MyClass { MyClass(const MyClass & arg) {} }" - # If the argument is a typedef, this is not a copy constructor. - # See the hierarchy of declarated_t and coumpound_t. They both - # inherit from type_t but are not related so we can discriminate - # between them. - return False - - # The argument needs to be passed by reference in a copy constructor - if not type_traits.is_reference(arg.decl_type): - return False - - # The argument needs to be const for a copy constructor - if not type_traits.is_const(arg.decl_type.base): - return False - - un_aliased = type_traits_utils.remove_alias(arg.decl_type.base) - # un_aliased now refers to const_t instance - if not isinstance(un_aliased.base, cpptypes.declarated_t): - # We are looking for a declaration - # If "class MyClass { MyClass(const int & arg) {} }" is used, - # this is not copy constructor, so we return False here. - # -> un_aliased.base == cpptypes.int_t (!= cpptypes.declarated_t) - return False - - # Final check: compare the parent (the class declaration for example) - # with the declaration of the type passed as argument. - return id(un_aliased.base.declaration) == id(self.parent) + return type_traits.is_copy_constructor(self.arguments, self.parent) @property def is_trivial_constructor(self): diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 5c6b6593..0f880df0 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -1290,3 +1290,50 @@ def is_std_wostream(type_): else: type_ = type_traits_utils.remove_alias(type_) return remove_cv(type_).decl_string in wostream_equivalences + + +def is_copy_constructor(args, parent): + """ + Returns True if described declaration is copy constructor, + otherwise False. + + """ + + # A copy constructor has only one argument + if len(args) != 1: + return False + + # We have only one argument, get it + arg = args[0] + + if not isinstance(arg.decl_type, cpptypes.compound_t): + # An argument of type declarated_t (a typedef) could be passed to + # the constructor; and it could be a reference. + # But in c++ you can NOT write : + # "typedef class MyClass { MyClass(const MyClass & arg) {} }" + # If the argument is a typedef, this is not a copy constructor. + # See the hierarchy of declarated_t and coumpound_t. They both + # inherit from type_t but are not related so we can discriminate + # between them. + return False + + # The argument needs to be passed by reference in a copy constructor + if not is_reference(arg.decl_type): + return False + + # The argument needs to be const for a copy constructor + if not is_const(arg.decl_type.base): + return False + + un_aliased = type_traits_utils.remove_alias(arg.decl_type.base) + # un_aliased now refers to const_t instance + if not isinstance(un_aliased.base, cpptypes.declarated_t): + # We are looking for a declaration + # If "class MyClass { MyClass(const int & arg) {} }" is used, + # this is not copy constructor, so we return False here. + # -> un_aliased.base == cpptypes.int_t (!= cpptypes.declarated_t) + return False + + # Final check: compare the parent (the class declaration for example) + # with the declaration of the type passed as argument. + return id(un_aliased.base.declaration) == id(parent) From 927c09bf51ddcaa37182bb936002350c1ae4405a Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 30 May 2016 23:04:33 +0200 Subject: [PATCH 155/268] Improve import path --- pygccxml/declarations/class_declaration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 6dd5abe8..d956fed0 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -16,7 +16,7 @@ from . import algorithm from . import declaration from . import dependencies -from pygccxml import utils +from .. import utils class ACCESS_TYPES(object): From fd84517e95675d446006de4d89bca147958b92b1 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 30 May 2016 23:19:36 +0200 Subject: [PATCH 156/268] Move some calldef consts/types to a separate module This fixes a cyclic import problem in class_declaration.py --- pygccxml/declarations/__init__.py | 7 ++-- pygccxml/declarations/calldef.py | 47 ++-------------------- pygccxml/declarations/calldef_members.py | 8 ++-- pygccxml/declarations/calldef_types.py | 45 +++++++++++++++++++++ pygccxml/declarations/class_declaration.py | 6 +-- pygccxml/declarations/free_calldef.py | 3 +- pygccxml/declarations/function_traits.py | 6 +-- pygccxml/parser/scanner.py | 2 +- 8 files changed, 66 insertions(+), 58 deletions(-) create mode 100644 pygccxml/declarations/calldef_types.py diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 1286aa28..8dac9c1f 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -93,9 +93,10 @@ from .algorithm import visit_function_has_not_been_found_t from .algorithm import get_global_namespace -from .calldef import VIRTUALITY_TYPES -from .calldef import FUNCTION_VIRTUALITY_TYPES -from .calldef import CALLING_CONVENTION_TYPES +from .calldef_types import VIRTUALITY_TYPES +from .calldef_types import FUNCTION_VIRTUALITY_TYPES +from .calldef_types import CALLING_CONVENTION_TYPES + from .calldef import argument_t from .calldef import calldef_t from .calldef_members import member_calldef_t diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index d681f782..4c5f0b93 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -16,7 +16,6 @@ - constructor - destructor """ -import re import warnings from . import cpptypes from . import algorithm @@ -24,48 +23,10 @@ from . import dependencies from . import call_invocation from . import type_traits_utils +from . import calldef_types from .. import utils -class VIRTUALITY_TYPES(object): - - """class that defines "virtuality" constants""" - NOT_VIRTUAL = 'not virtual' - VIRTUAL = 'virtual' - PURE_VIRTUAL = 'pure virtual' - ALL = [NOT_VIRTUAL, VIRTUAL, PURE_VIRTUAL] -# preserving backward compatebility -FUNCTION_VIRTUALITY_TYPES = VIRTUALITY_TYPES - - -class CALLING_CONVENTION_TYPES(object): - - """class that defines "calling convention" constants""" - UNKNOWN = '' - CDECL = 'cdecl' - STDCALL = 'stdcall' - THISCALL = 'thiscall' - FASTCALL = 'fastcall' - SYSTEM_DEFAULT = '<<>>' - - all = (UNKNOWN, CDECL, STDCALL, THISCALL, FASTCALL, SYSTEM_DEFAULT) - - pattern = re.compile( - r'.*(?:^|\s)(?:__)?(?Pcdecl|stdcall|thiscall|fastcall)(?:__)?.*') - - @staticmethod - def extract(text, default=UNKNOWN): - """extracts calling convention from the text. If the calling convention - could not be found, the "default"is used""" - if not text: - return default - found = CALLING_CONVENTION_TYPES.pattern.match(text) - if found: - return found.group('cc') - else: - return default - - # First level in hierarchy of calldef class argument_t(object): @@ -506,15 +467,15 @@ def i_depend_on_them(self, recursive=True): def guess_calling_convention(self): """This function should be overriden in the derived classes and return more-or-less successfull guess about calling convention""" - return CALLING_CONVENTION_TYPES.UNKNOWN + return calldef_types.CALLING_CONVENTION_TYPES.UNKNOWN @property def calling_convention(self): """function calling convention. See :class:CALLING_CONVENTION_TYPES class for possible values""" if self._calling_convention is None: - self._calling_convention = CALLING_CONVENTION_TYPES.extract( - self.attributes) + self._calling_convention = \ + calldef_types.CALLING_CONVENTION_TYPES.extract(self.attributes) if not self._calling_convention: self._calling_convention = self.guess_calling_convention() return self._calling_convention diff --git a/pygccxml/declarations/calldef_members.py b/pygccxml/declarations/calldef_members.py index 025b9165..80ed6e6f 100644 --- a/pygccxml/declarations/calldef_members.py +++ b/pygccxml/declarations/calldef_members.py @@ -6,7 +6,7 @@ from . import calldef from . import algorithm from . import cpptypes -from . import type_traits_utils +from . import calldef_types # Second level in hierarchy of calldef @@ -74,7 +74,7 @@ def virtuality(self): @virtuality.setter def virtuality(self, virtuality): - assert virtuality in calldef.VIRTUALITY_TYPES.ALL + assert virtuality in calldef_types.VIRTUALITY_TYPES.ALL self._virtuality = virtuality @property @@ -124,9 +124,9 @@ def create_decl_string(self, with_defaults=True): def guess_calling_convention(self): if self.has_static: - return calldef.CALLING_CONVENTION_TYPES.SYSTEM_DEFAULT + return calldef_types.CALLING_CONVENTION_TYPES.SYSTEM_DEFAULT else: - return calldef.CALLING_CONVENTION_TYPES.THISCALL + return calldef_types.CALLING_CONVENTION_TYPES.THISCALL class operator_t(object): diff --git a/pygccxml/declarations/calldef_types.py b/pygccxml/declarations/calldef_types.py new file mode 100644 index 00000000..406ea78e --- /dev/null +++ b/pygccxml/declarations/calldef_types.py @@ -0,0 +1,45 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +import re + + +class VIRTUALITY_TYPES(object): + + """class that defines "virtuality" constants""" + NOT_VIRTUAL = 'not virtual' + VIRTUAL = 'virtual' + PURE_VIRTUAL = 'pure virtual' + ALL = [NOT_VIRTUAL, VIRTUAL, PURE_VIRTUAL] +# preserving backward compatebility +FUNCTION_VIRTUALITY_TYPES = VIRTUALITY_TYPES + + +class CALLING_CONVENTION_TYPES(object): + + """class that defines "calling convention" constants""" + UNKNOWN = '' + CDECL = 'cdecl' + STDCALL = 'stdcall' + THISCALL = 'thiscall' + FASTCALL = 'fastcall' + SYSTEM_DEFAULT = '<<>>' + + all = (UNKNOWN, CDECL, STDCALL, THISCALL, FASTCALL, SYSTEM_DEFAULT) + + pattern = re.compile( + r'.*(?:^|\s)(?:__)?(?Pcdecl|stdcall|thiscall|fastcall)(?:__)?.*') + + @staticmethod + def extract(text, default=UNKNOWN): + """extracts calling convention from the text. If the calling convention + could not be found, the "default"is used""" + if not text: + return default + found = CALLING_CONVENTION_TYPES.pattern.match(text) + if found: + return found.group('cc') + else: + return default diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index d956fed0..5faa252a 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -16,6 +16,8 @@ from . import algorithm from . import declaration from . import dependencies +from . import calldef_members +from . import calldef_types from .. import utils @@ -631,12 +633,10 @@ def find_noncopyable_vars(self): @property def has_vtable(self): """True, if class has virtual table, False otherwise""" - from . import calldef - from . import calldef_members return bool( self.calldefs( lambda f: isinstance(f, calldef_members.member_function_t) and - f.virtuality != calldef.VIRTUALITY_TYPES.NOT_VIRTUAL, + f.virtuality != calldef_types.VIRTUALITY_TYPES.NOT_VIRTUAL, recursive=False, allow_empty=True)) diff --git a/pygccxml/declarations/free_calldef.py b/pygccxml/declarations/free_calldef.py index c6b9c6fc..bca19b60 100644 --- a/pygccxml/declarations/free_calldef.py +++ b/pygccxml/declarations/free_calldef.py @@ -5,6 +5,7 @@ from . import calldef from . import calldef_members +from . import calldef_types from . import algorithm from . import cpptypes from . import type_traits @@ -60,7 +61,7 @@ def create_decl_string(self, with_defaults=True): def guess_calling_convention(self): """This function should be overriden in the derived classes and return more-or-less successfull guess about calling convention""" - return calldef.CALLING_CONVENTION_TYPES.UNKNOWN + return calldef_types.CALLING_CONVENTION_TYPES.UNKNOWN class free_function_t(free_calldef_t): diff --git a/pygccxml/declarations/function_traits.py b/pygccxml/declarations/function_traits.py index 203d724e..6e462a1a 100644 --- a/pygccxml/declarations/function_traits.py +++ b/pygccxml/declarations/function_traits.py @@ -7,7 +7,7 @@ defines few algorithms, that deals with different properties of functions """ -from . import calldef +from . import calldef_types from . import calldef_members from . import type_traits @@ -34,8 +34,8 @@ def is_same_return_type(f1, f2): if not isinstance(f1, calldef_members.member_calldef_t): # for free functions we compare return types as usual return type_traits.is_same(f1.return_type, f2.return_type) - if f1.virtuality == calldef.VIRTUALITY_TYPES.NOT_VIRTUAL \ - or f2.virtuality == calldef.VIRTUALITY_TYPES.NOT_VIRTUAL: + if f1.virtuality == calldef_types.VIRTUALITY_TYPES.NOT_VIRTUAL \ + or f2.virtuality == calldef_types.VIRTUALITY_TYPES.NOT_VIRTUAL: # for non-virtual member functions we compare types as usual return type_traits.is_same(f1.return_type, f2.return_type) rt1 = f1.return_type diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index 6cc603a5..61456673 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -8,7 +8,7 @@ import xml.sax import xml.sax.handler from .. import utils -from pygccxml import declarations +from .. import declarations # convention # XML_NN - XML Node Name From c747a7c2b3600a59a7bad5ff5f9cf23296ad68fa Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 30 May 2016 23:27:07 +0200 Subject: [PATCH 157/268] The templates import can be done on top --- pygccxml/declarations/class_declaration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 5faa252a..2103a10e 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -18,6 +18,7 @@ from . import dependencies from . import calldef_members from . import calldef_types +from . import templates from .. import utils @@ -40,7 +41,6 @@ class CLASS_TYPES(object): def get_partial_name(name): - from . import templates from . import container_traits # prevent cyclic dependencies ct = container_traits.find_container_traits(name) if ct: From 2d00aba374b3c1c27a69af2c15489db21cfa9d47 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 30 May 2016 23:51:31 +0200 Subject: [PATCH 158/268] Remove unused __make_flatten_generator function This is used nowhere and not tested. Also, this method is marked as "private" with __, so it won't go through the deprecation process. It is not used in py++ and I had a quick look on github, and found no application. If somebody needs an equivalent functionality the function can be rewritten properly + tested later. --- pygccxml/declarations/algorithm.py | 34 ------------------------------ 1 file changed, 34 deletions(-) diff --git a/pygccxml/declarations/algorithm.py b/pygccxml/declarations/algorithm.py index 1df6e9b2..63fd5ffc 100644 --- a/pygccxml/declarations/algorithm.py +++ b/pygccxml/declarations/algorithm.py @@ -171,40 +171,6 @@ def proceed_single(decl): return answer -def __make_flatten_generator(decl_or_decls): - """ - Converts tree representation of declarations to flatten one. - - :param decl_or_decls: reference to list of declaration's or single - declaration - :type decl_or_decls: :class:`declaration_t` or [ :class:`declaration_t` ] - - :rtype: [ all internal declarations ] - - """ - - import pygccxml.declarations - - def proceed_single(decl): - yield decl - if not isinstance(decl, pygccxml.declarations.scopedef_t): - return - for internal in decl.declarations: - if isinstance(internal, pygccxml.declarations.scopedef_t): - for internal_internal in proceed_single(internal): - yield internal_internal - else: - yield internal - - if isinstance(decl_or_decls, list): - for creator in decl_or_decls: - for internal in proceed_single(creator): - yield internal - else: - for internal in proceed_single(decl_or_decls): - yield internal - - def get_global_namespace(decls): import pygccxml.declarations found = [ From 7b8d66af19cdb3228261724037d921f045e07770 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 31 May 2016 00:30:45 +0200 Subject: [PATCH 159/268] Organise and cleanup imports --- pygccxml/declarations/scopedef.py | 2 +- pygccxml/parser/source_reader.py | 47 +++++++++++++++---------------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/pygccxml/declarations/scopedef.py b/pygccxml/declarations/scopedef.py index 1c93db25..9b3f0c2e 100644 --- a/pygccxml/declarations/scopedef.py +++ b/pygccxml/declarations/scopedef.py @@ -11,8 +11,8 @@ from . import templates from . import declaration from . import mdecl_wrapper -from pygccxml import utils from . import matcher as matcher_module +from .. import utils import collections diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 8f9c080f..97a038c8 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -5,15 +5,14 @@ import os import platform +import subprocess from . import linker from . import config from . import patcher -import subprocess -import pygccxml.utils - -from .etree_scanner import ietree_scanner_t as scanner_t from . import declarations_cache -from pygccxml import utils +from .etree_scanner import ietree_scanner_t as scanner_t +from .. import utils + from pygccxml import declarations @@ -269,9 +268,9 @@ def create_xml_file(self, source_file, destination=None): xml_file = destination # If file specified, remove it to start else create new file name if xml_file: - pygccxml.utils.remove_file_no_raise(xml_file, self.__config) + utils.remove_file_no_raise(xml_file, self.__config) else: - xml_file = pygccxml.utils.create_temp_file_name(suffix='.xml') + xml_file = utils.create_temp_file_name(suffix='.xml') try: ffname = source_file if not os.path.isabs(ffname): @@ -311,7 +310,7 @@ def create_xml_file(self, source_file, destination=None): self.__config.xml_generator.upper() + ": %s" % gccxml_msg) except Exception: - pygccxml.utils.remove_file_no_raise(xml_file, self.__config) + utils.remove_file_no_raise(xml_file, self.__config) raise return xml_file @@ -327,14 +326,14 @@ def create_xml_file_from_string(self, content, destination=None): :rtype: returns file name of GCC-XML generated file """ - header_file = pygccxml.utils.create_temp_file_name(suffix='.h') + header_file = utils.create_temp_file_name(suffix='.h') try: with open(header_file, "w+") as header: header.write(content) xml_file = self.create_xml_file(header_file, destination) finally: - pygccxml.utils.remove_file_no_raise(header_file, self.__config) + utils.remove_file_no_raise(header_file, self.__config) return xml_file def read_file(self, source_file): @@ -367,10 +366,10 @@ def read_cpp_source_file(self, source_file): "from cache.")) except Exception: if xml_file: - pygccxml.utils.remove_file_no_raise(xml_file, self.__config) + utils.remove_file_no_raise(xml_file, self.__config) raise if xml_file: - pygccxml.utils.remove_file_no_raise(xml_file, self.__config) + utils.remove_file_no_raise(xml_file, self.__config) return decls @@ -407,16 +406,16 @@ def read_string(self, content): """ - header_file = pygccxml.utils.create_temp_file_name(suffix='.h') + header_file = utils.create_temp_file_name(suffix='.h') with open(header_file, "w+") as f: f.write(content) try: decls = self.read_file(header_file) except Exception: - pygccxml.utils.remove_file_no_raise(header_file, self.__config) + utils.remove_file_no_raise(header_file, self.__config) raise - pygccxml.utils.remove_file_no_raise(header_file, self.__config) + utils.remove_file_no_raise(header_file, self.__config) return decls @@ -466,7 +465,7 @@ def __parse_xml_file(self, xml_file): # Join declarations if self.__join_decls: for ns in iter(decls.values()): - if isinstance(ns, pygccxml.declarations.namespace_t): + if isinstance(ns, declarations.namespace_t): self.join_declarations(ns) # some times gccxml report typedefs defined in no namespace @@ -487,12 +486,12 @@ def __parse_xml_file(self, xml_file): def join_declarations(self, declref): self._join_namespaces(declref) for ns in declref.declarations: - if isinstance(ns, pygccxml.declarations.namespace_t): + if isinstance(ns, declarations.namespace_t): self.join_declarations(ns) @staticmethod def _join_namespaces(nsref): - assert isinstance(nsref, pygccxml.declarations.namespace_t) + assert isinstance(nsref, declarations.namespace_t) ddhash = {} decls = [] @@ -506,18 +505,18 @@ def _join_namespaces(nsref): decls.append(decl) joined_decls[decl._name] = [decl] else: - if isinstance(decl, pygccxml.declarations.calldef_t): + if isinstance(decl, declarations.calldef_t): if decl not in joined_decls[decl._name]: # functions has overloading decls.append(decl) joined_decls[decl._name].append(decl) - elif isinstance(decl, pygccxml.declarations.enumeration_t): + elif isinstance(decl, declarations.enumeration_t): # unnamed enums if not decl.name and decl not in \ joined_decls[decl._name]: decls.append(decl) joined_decls[decl._name].append(decl) - elif isinstance(decl, pygccxml.declarations.class_t): + elif isinstance(decl, declarations.class_t): # unnamed classes if not decl.name and decl not in \ joined_decls[decl._name]: @@ -525,11 +524,11 @@ def _join_namespaces(nsref): joined_decls[decl._name].append(decl) else: assert 1 == len(joined_decls[decl._name]) - if isinstance(decl, pygccxml.declarations.namespace_t): + if isinstance(decl, declarations.namespace_t): joined_decls[decl._name][0].take_parenting(decl) - class_t = pygccxml.declarations.class_t - class_declaration_t = pygccxml.declarations.class_declaration_t + class_t = declarations.class_t + class_declaration_t = declarations.class_declaration_t if class_t in ddhash and class_declaration_t in ddhash: # if there is a class and its forward declaration - get rid of the # second one. From 3b15ad17e988598e81c63aea0eb79c1493bf5c82 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 31 May 2016 00:32:45 +0200 Subject: [PATCH 160/268] Remove now unused import --- pygccxml/declarations/decl_printer.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pygccxml/declarations/decl_printer.py b/pygccxml/declarations/decl_printer.py index 1c657039..1fe00e95 100644 --- a/pygccxml/declarations/decl_printer.py +++ b/pygccxml/declarations/decl_printer.py @@ -10,7 +10,6 @@ import os import sys -from . import calldef from . import calldef_members from . import algorithm from . import decl_visitor From 7a6b75cd49c96903acb76c143e49b601f01fc21c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 31 May 2016 21:44:40 +0200 Subject: [PATCH 161/268] Move some functions from algorithm module to new declaration_utils module In the algorithm module, some functions are strongly linked to scopedef classes. Algorithm is imported at a lot of places, which created some potentials conflicts and made refactoring difficult. Now, instead of importing algorithm everywhere, only the module with the 4 needed functions is imported. This module has the advantage that it has no other dependencies, making it self-contained. --- pygccxml/declarations/__init__.py | 8 +- pygccxml/declarations/algorithm.py | 108 +------------------- pygccxml/declarations/calldef.py | 6 +- pygccxml/declarations/calldef_members.py | 6 +- pygccxml/declarations/class_declaration.py | 28 +++--- pygccxml/declarations/declaration.py | 11 +-- pygccxml/declarations/declaration_utils.py | 109 +++++++++++++++++++++ pygccxml/declarations/free_calldef.py | 4 +- pygccxml/declarations/matchers.py | 13 ++- pygccxml/declarations/namespace.py | 4 +- 10 files changed, 152 insertions(+), 145 deletions(-) create mode 100644 pygccxml/declarations/declaration_utils.py diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 8dac9c1f..426767b3 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -76,14 +76,14 @@ from .cpptypes import jchar_t from .cpptypes import jboolean_t - from .variable import variable_t -from .algorithm import full_name -from .algorithm import full_name_from_declaration_path +from .declaration_utils import full_name +from .declaration_utils import full_name_from_declaration_path +from .declaration_utils import declaration_path + from .algorithm import make_flatten from .algorithm import apply_visitor -from .algorithm import declaration_path from .algorithm import get_named_parent from .algorithm import find_declaration from .algorithm import match_declaration_t diff --git a/pygccxml/declarations/algorithm.py b/pygccxml/declarations/algorithm.py index 63fd5ffc..9536c2a3 100644 --- a/pygccxml/declarations/algorithm.py +++ b/pygccxml/declarations/algorithm.py @@ -9,76 +9,7 @@ """ import warnings - - -def declaration_path(decl, with_defaults=True): - """ - Returns a list of parent declarations names. - - :param decl: declaration for which declaration path should be calculated - :type decl: :class:`declaration_t` - - :rtype: [names], where first item contains top parent name and last item - contains the `decl` name - - """ - - if not decl: - return [] - if not decl.cache.declaration_path: - result = [decl.name] - parent = decl.parent - while parent: - if parent.cache.declaration_path: - result.reverse() - decl.cache.declaration_path = parent.cache.declaration_path + \ - result - return decl.cache.declaration_path - else: - result.append(parent.name) - parent = parent.parent - result.reverse() - decl.cache.declaration_path = result - return result - else: - return decl.cache.declaration_path - - -def partial_declaration_path(decl): - """ - Returns a list of parent declarations names without template arguments that - have default value. - - :param decl: declaration for which declaration path should be calculated - :type decl: :class:`declaration_t` - - :rtype: [names], where first item contains top parent name and last item - contains the `decl` name - - """ - - # TODO: - # If parent declaration cache already has declaration_path, reuse it for - # calculation. - if not decl: - return [] - if not decl.cache.partial_declaration_path: - result = [decl.partial_name] - parent = decl.parent - while parent: - if parent.cache.partial_declaration_path: - result.reverse() - decl.cache.partial_declaration_path \ - = parent.cache.partial_declaration_path + result - return decl.cache.partial_declaration_path - else: - result.append(parent.partial_name) - parent = parent.parent - result.reverse() - decl.cache.partial_declaration_path = result - return result - else: - return decl.cache.partial_declaration_path +from . import declaration_utils def get_named_parent(decl): @@ -101,41 +32,6 @@ def get_named_parent(decl): return parent -def full_name_from_declaration_path(dpath): - # Here I have lack of knowledge: - # TODO: "What is the full name of declaration declared in unnamed - # namespace?" - result = [_f for _f in dpath if _f] - result = result[0] + '::'.join(result[1:]) - return result - - -def full_name(decl, with_defaults=True): - """ - Returns declaration full qualified name. - - If `decl` belongs to anonymous namespace or class, the function will return - C++ illegal qualified name. - :param decl: :class:`declaration_t` - :type decl: :class:`declaration_t` - :rtype: full name of declarations. - - """ - - if None is decl: - raise RuntimeError("Unable to generate full name for None object!") - if with_defaults: - if not decl.cache.full_name: - decl.cache.full_name = full_name_from_declaration_path( - declaration_path(decl)) - return decl.cache.full_name - else: - if not decl.cache.full_partial_name: - decl.cache.full_partial_name = full_name_from_declaration_path( - partial_declaration_path(decl)) - return decl.cache.full_partial_name - - def make_flatten(decl_or_decls): """ Converts tree representation of declarations to flatten one. @@ -236,7 +132,7 @@ def does_match_exist(self, inst): answer &= self.parent is inst.parent if self.fullname is not None: if inst.name: - answer &= self.fullname == full_name(inst) + answer &= self.fullname == declaration_utils.full_name(inst) else: answer = False return answer diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index 4c5f0b93..8c1dc488 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -18,7 +18,7 @@ """ import warnings from . import cpptypes -from . import algorithm +from . import declaration_utils from . import declaration from . import dependencies from . import call_invocation @@ -382,7 +382,7 @@ def has_inline(self, has_inline): def __remove_parent_fname(self, demangled): """implementation details""" demangled = demangled.strip() - parent_fname = algorithm.full_name(self.parent) + parent_fname = declaration_utils.full_name(self.parent) if parent_fname.startswith('::') and not demangled.startswith('::'): parent_fname = parent_fname[2:] demangled = demangled[len(parent_fname):] @@ -429,7 +429,7 @@ def demangled_name(self): return self._demangled_name # well, I am going to try an other strategy - fname = algorithm.full_name(self) + fname = declaration_utils.full_name(self) found = self.demangled.find(fname) if -1 == found: if fname.startswith('::'): diff --git a/pygccxml/declarations/calldef_members.py b/pygccxml/declarations/calldef_members.py index 80ed6e6f..d48c9cd1 100644 --- a/pygccxml/declarations/calldef_members.py +++ b/pygccxml/declarations/calldef_members.py @@ -4,7 +4,7 @@ # See http://www.boost.org/LICENSE_1_0.txt from . import calldef -from . import algorithm +from . import declaration_utils from . import cpptypes from . import calldef_types @@ -29,7 +29,7 @@ def __init__( def __str__(self): # Get the full name of the calldef... - name = algorithm.full_name(self) + name = declaration_utils.full_name(self) if name[:2] == "::": name = name[2:] # Add the arguments... @@ -175,7 +175,7 @@ def explicit(self, explicit): def __str__(self): # Get the full name of the calldef... - name = algorithm.full_name(self) + name = declaration_utils.full_name(self) if name[:2] == "::": name = name[2:] # Add the arguments... diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 2103a10e..0f3a0378 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -13,7 +13,7 @@ """ from . import scopedef -from . import algorithm +from . import declaration_utils from . import declaration from . import dependencies from . import calldef_members @@ -72,13 +72,13 @@ def __init__(self, related_class=None, access=None, is_virtual=False): def __eq__(self, other): if not isinstance(other, hierarchy_info_t): return False - return algorithm.declaration_path(self.related_class) == \ - algorithm.declaration_path(other.related_class) \ + return declaration_utils.declaration_path(self.related_class) == \ + declaration_utils.declaration_path(other.related_class) \ and self.access == other.access \ and self.is_virtual == other.is_virtual def __hash__(self): - return hash(algorithm.declaration_path(self.related_class)) + return hash(declaration_utils.declaration_path(self.related_class)) def __ne__(self, other): return not self.__eq__(other) @@ -87,10 +87,10 @@ def __lt__(self, other): if not isinstance(other, self.__class__): return self.__class__.__name__ < other.__class__.__name__ return ( - algorithm.declaration_path(self.related_class), + declaration_utils.declaration_path(self.related_class), self.access, self.is_virtual) < ( - algorithm.declaration_path( + declaration_utils.declaration_path( other.related_class), other.access, self.is_virtual) @@ -228,7 +228,7 @@ def _get_name_impl(self): elif self.use_demangled_as_name and self.demangled: if not self.cache.demangled_name: - fname = algorithm.full_name(self.parent) + fname = declaration_utils.full_name(self.parent) if fname.startswith('::') and \ not self.demangled.startswith('::'): fname = fname[2:] @@ -255,7 +255,7 @@ def _get_name_impl(self): return self._name def __str__(self): - name = algorithm.full_name(self) + name = declaration_utils.full_name(self) if name[:2] == "::": name = name[2:] return "%s [%s]" % (name, self.class_type) @@ -264,10 +264,10 @@ def _get__cmp__scope_items(self): """implementation details""" return [self.class_type, self._sorted_list( - [algorithm.declaration_path(base.related_class) + [declaration_utils.declaration_path(base.related_class) for base in self.bases]), self._sorted_list( - [algorithm.declaration_path(derive.related_class) + [declaration_utils.declaration_path(derive.related_class) for derive in self.derived]), self.is_abstract, self._sorted_list(self.public_members), @@ -279,16 +279,16 @@ def __eq__(self, other): return False return self.class_type == other.class_type \ and self._sorted_list( - [algorithm.declaration_path(base.related_class) + [declaration_utils.declaration_path(base.related_class) for base in self.bases]) \ == other._sorted_list( - [algorithm.declaration_path(base.related_class) + [declaration_utils.declaration_path(base.related_class) for base in other.bases]) \ and self._sorted_list( - [algorithm.declaration_path(derive.related_class) + [declaration_utils.declaration_path(derive.related_class) for derive in self.derived]) \ == other._sorted_list( - [algorithm.declaration_path(derive.related_class) + [declaration_utils.declaration_path(derive.related_class) for derive in other.derived]) \ and self.is_abstract == other.is_abstract \ and self._sorted_list(self.public_members) \ diff --git a/pygccxml/declarations/declaration.py b/pygccxml/declarations/declaration.py index 65adb136..db07c728 100644 --- a/pygccxml/declarations/declaration.py +++ b/pygccxml/declarations/declaration.py @@ -9,7 +9,7 @@ """ -from . import algorithm +from . import declaration_utils from . import algorithms_cache from .. import utils @@ -93,8 +93,7 @@ def _get__cmp__data(self): """ data = [ - algorithm.declaration_path( - self.parent), + declaration_utils.declaration_path(self.parent), self.name, self.location] data.extend(self._get__cmp__items()) @@ -116,8 +115,8 @@ def __eq__(self, other): return False return self.name == other.name \ and self.location == other.location \ - and algorithm.declaration_path(self.parent) \ - == algorithm.declaration_path(other.parent) + and declaration_utils.declaration_path(self.parent) \ + == declaration_utils.declaration_path(other.parent) def __hash__(self): return (hash(self.__class__) ^ @@ -339,7 +338,7 @@ def attributes(self, attributes): self._attributes = attributes def create_decl_string(self, with_defaults=True): - return algorithm.full_name(self, with_defaults) + return declaration_utils.full_name(self, with_defaults) @property def decl_string(self): diff --git a/pygccxml/declarations/declaration_utils.py b/pygccxml/declarations/declaration_utils.py new file mode 100644 index 00000000..3e188f03 --- /dev/null +++ b/pygccxml/declarations/declaration_utils.py @@ -0,0 +1,109 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + + +def declaration_path(decl, with_defaults=True): + """ + Returns a list of parent declarations names. + + :param decl: declaration for which declaration path should be calculated + :type decl: :class:`declaration_t` + + :rtype: [names], where first item contains top parent name and last item + contains the `decl` name + + """ + + if not decl: + return [] + if not decl.cache.declaration_path: + result = [decl.name] + parent = decl.parent + while parent: + if parent.cache.declaration_path: + result.reverse() + decl.cache.declaration_path = parent.cache.declaration_path + \ + result + return decl.cache.declaration_path + else: + result.append(parent.name) + parent = parent.parent + result.reverse() + decl.cache.declaration_path = result + return result + else: + return decl.cache.declaration_path + + +def partial_declaration_path(decl): + """ + Returns a list of parent declarations names without template arguments that + have default value. + + :param decl: declaration for which declaration path should be calculated + :type decl: :class:`declaration_t` + + :rtype: [names], where first item contains top parent name and last item + contains the `decl` name + + """ + + # TODO: + # If parent declaration cache already has declaration_path, reuse it for + # calculation. + if not decl: + return [] + if not decl.cache.partial_declaration_path: + result = [decl.partial_name] + parent = decl.parent + while parent: + if parent.cache.partial_declaration_path: + result.reverse() + decl.cache.partial_declaration_path \ + = parent.cache.partial_declaration_path + result + return decl.cache.partial_declaration_path + else: + result.append(parent.partial_name) + parent = parent.parent + result.reverse() + decl.cache.partial_declaration_path = result + return result + else: + return decl.cache.partial_declaration_path + + +def full_name_from_declaration_path(dpath): + # Here I have lack of knowledge: + # TODO: "What is the full name of declaration declared in unnamed + # namespace?" + result = [_f for _f in dpath if _f] + result = result[0] + '::'.join(result[1:]) + return result + + +def full_name(decl, with_defaults=True): + """ + Returns declaration full qualified name. + + If `decl` belongs to anonymous namespace or class, the function will return + C++ illegal qualified name. + :param decl: :class:`declaration_t` + :type decl: :class:`declaration_t` + :rtype: full name of declarations. + + """ + + if None is decl: + raise RuntimeError("Unable to generate full name for None object!") + if with_defaults: + if not decl.cache.full_name: + decl.cache.full_name = full_name_from_declaration_path( + declaration_path(decl)) + return decl.cache.full_name + else: + if not decl.cache.full_partial_name: + decl.cache.full_partial_name = full_name_from_declaration_path( + partial_declaration_path(decl)) + return decl.cache.full_partial_name diff --git a/pygccxml/declarations/free_calldef.py b/pygccxml/declarations/free_calldef.py index bca19b60..73bc015d 100644 --- a/pygccxml/declarations/free_calldef.py +++ b/pygccxml/declarations/free_calldef.py @@ -6,7 +6,7 @@ from . import calldef from . import calldef_members from . import calldef_types -from . import algorithm +from . import declaration_utils from . import cpptypes from . import type_traits @@ -21,7 +21,7 @@ def __init__(self, *args, **keywords): def __str__(self): # Get the full name of the calldef... - name = algorithm.full_name(self) + name = declaration_utils.full_name(self) if name[:2] == "::": name = name[2:] # Add the arguments... diff --git a/pygccxml/declarations/matchers.py b/pygccxml/declarations/matchers.py index 18eaa5da..eb53a720 100644 --- a/pygccxml/declarations/matchers.py +++ b/pygccxml/declarations/matchers.py @@ -11,7 +11,7 @@ import os import re import warnings -from . import algorithm +from . import declaration_utils from . import variable from . import namespace from . import calldef @@ -272,17 +272,20 @@ def check_name(self, decl): return False else: if self.name != templates.normalize( - algorithm.full_name(decl, with_defaults=True)) \ + declaration_utils.full_name( + decl, with_defaults=True)) \ and self.name != templates.normalize( - algorithm.full_name(decl, with_defaults=False)): + declaration_utils.full_name( + decl, with_defaults=False)): return False else: if not self.__opt_is_full_name: if self.name != decl.name and self.name != decl.partial_name: return False else: - if self.name != algorithm.full_name(decl, with_defaults=True) \ - and self.name != algorithm.full_name( + if self.name != declaration_utils.full_name( + decl, with_defaults=True) \ + and self.name != declaration_utils.full_name( decl, with_defaults=False): return False return True diff --git a/pygccxml/declarations/namespace.py b/pygccxml/declarations/namespace.py index 41e8593e..8642445b 100644 --- a/pygccxml/declarations/namespace.py +++ b/pygccxml/declarations/namespace.py @@ -10,7 +10,7 @@ import warnings from . import scopedef -from . import algorithm +from . import declaration_utils class namespace_t(scopedef.scopedef_t): @@ -32,7 +32,7 @@ def __init__(self, name='', declarations=None): self._declarations = declarations def __str__(self): - name = algorithm.full_name(self) + name = declaration_utils.full_name(self) if name != "::" and name[:2] == "::": name = name[2:] return "%s [namespace]" % name From ba76ecbc7839d0b886eff0146a988b2598b0fb79 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 31 May 2016 21:50:12 +0200 Subject: [PATCH 162/268] Move get_named_parent function to declaration_utils module This function uses no specific imports; so it can also be moved to the new module. Note that it seems not to be used, so it may be a good candidate for a later deprecation. --- pygccxml/declarations/__init__.py | 2 +- pygccxml/declarations/algorithm.py | 20 -------------------- pygccxml/declarations/declaration_utils.py | 20 ++++++++++++++++++++ 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 426767b3..d63e2f5d 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -81,10 +81,10 @@ from .declaration_utils import full_name from .declaration_utils import full_name_from_declaration_path from .declaration_utils import declaration_path +from .declaration_utils import get_named_parent from .algorithm import make_flatten from .algorithm import apply_visitor -from .algorithm import get_named_parent from .algorithm import find_declaration from .algorithm import match_declaration_t from .algorithm import find_all_declarations diff --git a/pygccxml/declarations/algorithm.py b/pygccxml/declarations/algorithm.py index 9536c2a3..11321e63 100644 --- a/pygccxml/declarations/algorithm.py +++ b/pygccxml/declarations/algorithm.py @@ -12,26 +12,6 @@ from . import declaration_utils -def get_named_parent(decl): - """ - Returns a reference to a named parent declaration. - - :param decl: the child declaration - :type decl: :class:`declaration_t` - - :rtype: reference to :class:`declaration_t` or None if not found - - """ - - if not decl: - return None - - parent = decl.parent - while parent and (not parent.name or parent.name == '::'): - parent = parent.parent - return parent - - def make_flatten(decl_or_decls): """ Converts tree representation of declarations to flatten one. diff --git a/pygccxml/declarations/declaration_utils.py b/pygccxml/declarations/declaration_utils.py index 3e188f03..4d929a8a 100644 --- a/pygccxml/declarations/declaration_utils.py +++ b/pygccxml/declarations/declaration_utils.py @@ -107,3 +107,23 @@ def full_name(decl, with_defaults=True): decl.cache.full_partial_name = full_name_from_declaration_path( partial_declaration_path(decl)) return decl.cache.full_partial_name + + +def get_named_parent(decl): + """ + Returns a reference to a named parent declaration. + + :param decl: the child declaration + :type decl: :class:`declaration_t` + + :rtype: reference to :class:`declaration_t` or None if not found + + """ + + if not decl: + return None + + parent = decl.parent + while parent and (not parent.name or parent.name == '::'): + parent = parent.parent + return parent From a2f07689c58573a1eac83114c0b0bb5c768413a7 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 31 May 2016 22:12:32 +0200 Subject: [PATCH 163/268] Move make_flatten and find functions to scopef module The make_flatten function needs scopedef. This fixes some cyclic imports problems. The matcher class also needed to move to scopef for this to work The scopedef module is getting bigger but we can still refactor it later to make it shorter --- pygccxml/declarations/__init__.py | 16 +- pygccxml/declarations/algorithm.py | 200 ----------------- pygccxml/declarations/matcher.py | 108 --------- pygccxml/declarations/scopedef.py | 319 ++++++++++++++++++++++++++- pygccxml/declarations/type_traits.py | 7 +- 5 files changed, 322 insertions(+), 328 deletions(-) delete mode 100644 pygccxml/declarations/matcher.py diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index d63e2f5d..eec3145f 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -83,15 +83,17 @@ from .declaration_utils import declaration_path from .declaration_utils import get_named_parent -from .algorithm import make_flatten +from .scopedef import make_flatten +from .scopedef import find_declaration +from .scopedef import find_all_declarations +from .scopedef import find_first_declaration +from .scopedef import declaration_files +from .scopedef import get_global_namespace +from .scopedef import matcher + from .algorithm import apply_visitor -from .algorithm import find_declaration from .algorithm import match_declaration_t -from .algorithm import find_all_declarations -from .algorithm import find_first_declaration -from .algorithm import declaration_files from .algorithm import visit_function_has_not_been_found_t -from .algorithm import get_global_namespace from .calldef_types import VIRTUALITY_TYPES from .calldef_types import FUNCTION_VIRTUALITY_TYPES @@ -225,8 +227,6 @@ from .matchers import custom_matcher_t from .matchers import virtuality_type_matcher_t -from .matcher import matcher - from .mdecl_wrapper import mdecl_wrapper_t from .decl_printer import decl_printer_t diff --git a/pygccxml/declarations/algorithm.py b/pygccxml/declarations/algorithm.py index 11321e63..d0ff80f9 100644 --- a/pygccxml/declarations/algorithm.py +++ b/pygccxml/declarations/algorithm.py @@ -12,51 +12,6 @@ from . import declaration_utils -def make_flatten(decl_or_decls): - """ - Converts tree representation of declarations to flatten one. - - :param decl_or_decls: reference to list of declaration's or single - declaration - :type decl_or_decls: :class:`declaration_t` or [ :class:`declaration_t` ] - :rtype: [ all internal declarations ] - - """ - - import pygccxml.declarations # prevent cyclic import - - def proceed_single(decl): - answer = [decl] - if not isinstance(decl, pygccxml.declarations.scopedef_t): - return answer - for elem in decl.declarations: - if isinstance(elem, pygccxml.declarations.scopedef_t): - answer.extend(proceed_single(elem)) - else: - answer.append(elem) - return answer - - decls = [] - if isinstance(decl_or_decls, list): - decls.extend(decl_or_decls) - else: - decls.append(decl_or_decls) - answer = [] - for decl in decls: - answer.extend(proceed_single(decl)) - return answer - - -def get_global_namespace(decls): - import pygccxml.declarations - found = [ - decl for decl in make_flatten(decls) if decl.name == '::' and - isinstance(decl, pygccxml.declarations.namespace_t)] - if len(found) == 1: - return found[0] - raise RuntimeError("Unable to find global namespace.") - - class match_declaration_t(object): """ Helper class for different search algorithms. @@ -128,161 +83,6 @@ def __call__(self, inst): return self.does_match_exist(inst) -def find_all_declarations( - declarations, - type=None, - decl_type=None, - name=None, - parent=None, - recursive=True, - fullname=None): - """ - Returns a list of all declarations that match criteria, defined by - developer. - - For more information about arguments see :class:`match_declaration_t` - class. - - :rtype: [ matched declarations ] - - """ - if type is not None: - # Deprecated since 1.8.0. Will be removed in 1.9.0 - warnings.warn( - "The type argument is deprecated. \n" + - "Please use the decl_type argument instead.", - DeprecationWarning) - if decl_type is not None: - raise ( - "Please use only either the type or " + - "decl_type argument.") - # Still allow to use the old type for the moment. - decl_type = type - - if recursive: - decls = make_flatten(declarations) - else: - decls = declarations - - return list( - filter( - match_declaration_t( - decl_type=decl_type, - name=name, - fullname=fullname, - parent=parent), - decls)) - - -def find_declaration( - declarations, - type=None, - decl_type=None, - name=None, - parent=None, - recursive=True, - fullname=None): - """ - Returns single declaration that match criteria, defined by developer. - If more the one declaration was found None will be returned. - - For more information about arguments see :class:`match_declaration_t` - class. - - :rtype: matched declaration :class:`declaration_t` or None - - """ - if type is not None: - # Deprecated since 1.8.0. Will be removed in 1.9.0 - warnings.warn( - "The type argument is deprecated. \n" + - "Please use the decl_type argument instead.", - DeprecationWarning) - if decl_type is not None: - raise ( - "Please use only either the type or " + - "decl_type argument.") - # Still allow to use the old type for the moment. - decl_type = type - - decl = find_all_declarations( - declarations, - decl_type=decl_type, - name=name, - parent=parent, - recursive=recursive, - fullname=fullname) - if len(decl) == 1: - return decl[0] - - -def find_first_declaration( - declarations, - type=None, - decl_type=None, - name=None, - parent=None, - recursive=True, - fullname=None): - """ - Returns first declaration that match criteria, defined by developer. - - For more information about arguments see :class:`match_declaration_t` - class. - - :rtype: matched declaration :class:`declaration_t` or None - - """ - if type is not None: - # Deprecated since 1.8.0. Will be removed in 1.9.0 - warnings.warn( - "The type argument is deprecated. \n" + - "Please use the decl_type argument instead.", - DeprecationWarning) - if decl_type is not None: - raise ( - "Please use only either the type or " + - "decl_type argument.") - # Still allow to use the old type for the moment. - decl_type = type - - matcher = match_declaration_t( - decl_type=decl_type, - name=name, - fullname=fullname, - parent=parent) - if recursive: - decls = make_flatten(declarations) - else: - decls = declarations - for decl in decls: - if matcher(decl): - return decl - return None - - -def declaration_files(decl_or_decls): - """ - Returns set of files - - Every declaration is declared in some file. This function returns set, that - contains all file names of declarations. - - :param decl_or_decls: reference to list of declaration's or single - declaration - :type decl_or_decls: :class:`declaration_t` or [:class:`declaration_t`] - :rtype: set(declaration file names) - - """ - - files = set() - decls = make_flatten(decl_or_decls) - for decl in decls: - if decl.location: - files.add(decl.location.file_name) - return files - - class visit_function_has_not_been_found_t(RuntimeError): """ Exception that is raised, from :func:`apply_visitor`, when a visitor could diff --git a/pygccxml/declarations/matcher.py b/pygccxml/declarations/matcher.py deleted file mode 100644 index 8779b710..00000000 --- a/pygccxml/declarations/matcher.py +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright 2014-2016 Insight Software Consortium. -# Copyright 2004-2008 Roman Yakovenko. -# Distributed under the Boost Software License, Version 1.0. -# See http://www.boost.org/LICENSE_1_0.txt - -"""Implements a few "find" algorithms on declarations tree""" - -from . import algorithm - - -class matcher(object): - - """Class-namespace, contains implementation of a few "find" algorithms - and definition of the related exception classes""" - - class declaration_not_found_t(RuntimeError): - - """Exception raised when the declaration could not be found""" - - def __init__(self, matcher): - RuntimeError.__init__(self) - self.matcher = matcher - - def __str__(self): - return ( - "Unable to find declaration. Matcher: [%s]" % str( - self.matcher) - ) - - class multiple_declarations_found_t(RuntimeError): - - """Exception raised when more than one declaration was found""" - - def __init__(self, matcher): - RuntimeError.__init__(self) - self.matcher = matcher - - def __str__(self): - return ( - "Multiple declarations have been found. Matcher: [%s]" % str( - self.matcher) - ) - - @staticmethod - def find(decl_matcher, decls, recursive=True): - """ - Returns a list of declarations that match `decl_matcher` defined - criteria or None - - :param decl_matcher: Python callable object, that takes one argument - - reference to a declaration - :param decls: the search scope, :class:declaration_t object or - :class:declaration_t objects list t - :param recursive: boolean, if True, the method will run `decl_matcher` - on the internal declarations too - """ - - where = [] - if isinstance(decls, list): - where.extend(decls) - else: - where.append(decls) - if recursive: - where = algorithm.make_flatten(where) - return list(filter(decl_matcher, where)) - - @staticmethod - def find_single(decl_matcher, decls, recursive=True): - """ - Returns a reference to the declaration, that match `decl_matcher` - defined criteria. - - if a unique declaration could not be found the method will return None. - - :param decl_matcher: Python callable object, that takes one argument - - reference to a declaration - :param decls: the search scope, :class:declaration_t object or - :class:declaration_t objects list t - :param recursive: boolean, if True, the method will run `decl_matcher` - on the internal declarations too - """ - answer = matcher.find(decl_matcher, decls, recursive) - if len(answer) == 1: - return answer[0] - - @staticmethod - def get_single(decl_matcher, decls, recursive=True): - """ - Returns a reference to declaration, that match `decl_matcher` defined - criteria. - - If a unique declaration could not be found, an appropriate exception - will be raised. - - :param decl_matcher: Python callable object, that takes one argument - - reference to a declaration - :param decls: the search scope, :class:declaration_t object or - :class:declaration_t objects list t - :param recursive: boolean, if True, the method will run `decl_matcher` - on the internal declarations too - """ - answer = matcher.find(decl_matcher, decls, recursive) - if len(answer) == 1: - return answer[0] - elif not answer: - raise matcher.declaration_not_found_t(decl_matcher) - else: - raise matcher.multiple_declarations_found_t(decl_matcher) diff --git a/pygccxml/declarations/scopedef.py b/pygccxml/declarations/scopedef.py index 9b3f0c2e..14aada2d 100644 --- a/pygccxml/declarations/scopedef.py +++ b/pygccxml/declarations/scopedef.py @@ -7,13 +7,115 @@ import time import warnings +import collections from . import algorithm from . import templates from . import declaration from . import mdecl_wrapper -from . import matcher as matcher_module from .. import utils -import collections + + +class matcher(object): + + """Class-namespace, contains implementation of a few "find" algorithms + and definition of the related exception classes""" + + class declaration_not_found_t(RuntimeError): + + """Exception raised when the declaration could not be found""" + + def __init__(self, matcher): + RuntimeError.__init__(self) + self.matcher = matcher + + def __str__(self): + return ( + "Unable to find declaration. Matcher: [%s]" % str( + self.matcher) + ) + + class multiple_declarations_found_t(RuntimeError): + + """Exception raised when more than one declaration was found""" + + def __init__(self, matcher): + RuntimeError.__init__(self) + self.matcher = matcher + + def __str__(self): + return ( + "Multiple declarations have been found. Matcher: [%s]" % str( + self.matcher) + ) + + @staticmethod + def find(decl_matcher, decls, recursive=True): + """ + Returns a list of declarations that match `decl_matcher` defined + criteria or None + + :param decl_matcher: Python callable object, that takes one argument - + reference to a declaration + :param decls: the search scope, :class:declaration_t object or + :class:declaration_t objects list t + :param recursive: boolean, if True, the method will run `decl_matcher` + on the internal declarations too + """ + + where = [] + if isinstance(decls, list): + where.extend(decls) + else: + where.append(decls) + if recursive: + where = make_flatten(where) + return list(filter(decl_matcher, where)) + + @staticmethod + def find_single(decl_matcher, decls, recursive=True): + """ + Returns a reference to the declaration, that match `decl_matcher` + defined criteria. + + if a unique declaration could not be found the method will return None. + + :param decl_matcher: Python callable object, that takes one argument - + reference to a declaration + :param decls: the search scope, :class:declaration_t object or + :class:declaration_t objects list t + :param recursive: boolean, if True, the method will run `decl_matcher` + on the internal declarations too + """ + answer = _matcher.find(decl_matcher, decls, recursive) + if len(answer) == 1: + return answer[0] + + @staticmethod + def get_single(decl_matcher, decls, recursive=True): + """ + Returns a reference to declaration, that match `decl_matcher` defined + criteria. + + If a unique declaration could not be found, an appropriate exception + will be raised. + + :param decl_matcher: Python callable object, that takes one argument - + reference to a declaration + :param decls: the search scope, :class:declaration_t object or + :class:declaration_t objects list t + :param recursive: boolean, if True, the method will run `decl_matcher` + on the internal declarations too + """ + answer = _matcher.find(decl_matcher, decls, recursive) + if len(answer) == 1: + return answer[0] + elif not answer: + raise _matcher.declaration_not_found_t(decl_matcher) + else: + raise _matcher.multiple_declarations_found_t(decl_matcher) + +# FIXME: this is ugly +_matcher = matcher class scopedef_t(declaration.declaration_t): @@ -70,9 +172,8 @@ class scopedef_t(declaration.declaration_t): RECURSIVE_DEFAULT = True ALLOW_EMPTY_MDECL_WRAPPER = False - declaration_not_found_t = matcher_module.matcher.declaration_not_found_t - multiple_declarations_found_t = \ - matcher_module.matcher.multiple_declarations_found_t + declaration_not_found_t = _matcher.declaration_not_found_t + multiple_declarations_found_t = _matcher.multiple_declarations_found_t # this class variable is used to prevent recursive imports _impl_matchers = {} @@ -205,7 +306,7 @@ def init_optimizer(self): self._type2name2decls_nr[dtype] = {} self._all_decls_not_recursive = self.declarations - self._all_decls = algorithm.make_flatten( + self._all_decls = make_flatten( self._all_decls_not_recursive) for decl in self._all_decls: types = self.__decl_types(decl) @@ -327,7 +428,7 @@ def __findout_range(self, name, decl_type, recursive): 'running non optimized query - optimization has not been done') decls = self.declarations if recursive: - decls = algorithm.make_flatten(self.declarations) + decls = make_flatten(self.declarations) if decl_type: decls = [d for d in decls if isinstance(d, decl_type)] return decls @@ -384,7 +485,7 @@ def _find_single(self, match_class, **keywds): dtype = self.__findout_decl_type(match_class, **norm_keywds) recursive_ = self.__findout_recursive(**norm_keywds) decls = self.__findout_range(norm_keywds['name'], dtype, recursive_) - found = matcher_module.matcher.get_single(matcher, decls, False) + found = _matcher.get_single(matcher, decls, False) self._logger.debug( 'find single query execution - done( %f seconds )' % (time.clock() - start_time)) @@ -400,7 +501,7 @@ def _find_multiple(self, match_class, **keywds): recursive_ = self.__findout_recursive(**norm_keywds) allow_empty = self.__findout_allow_empty(**norm_keywds) decls = self.__findout_range(norm_keywds['name'], dtype, recursive_) - found = matcher_module.matcher.find(matcher, decls, False) + found = _matcher.find(matcher, decls, False) mfound = mdecl_wrapper.mdecl_wrapper_t(found) self._logger.debug('%d declaration(s) that match query' % len(mfound)) self._logger.debug('find single query execution - done( %f seconds )' @@ -1049,3 +1150,203 @@ def __getitem__(self, name_or_function): :param name_or_function: Name of `decl` to lookup or finder function. """ return self.decls(name_or_function) + + +def make_flatten(decl_or_decls): + """ + Converts tree representation of declarations to flatten one. + + :param decl_or_decls: reference to list of declaration's or single + declaration + :type decl_or_decls: :class:`declaration_t` or [ :class:`declaration_t` ] + :rtype: [ all internal declarations ] + + """ + + def proceed_single(decl): + answer = [decl] + if not isinstance(decl, scopedef_t): + return answer + for elem in decl.declarations: + if isinstance(elem, scopedef_t): + answer.extend(proceed_single(elem)) + else: + answer.append(elem) + return answer + + decls = [] + if isinstance(decl_or_decls, list): + decls.extend(decl_or_decls) + else: + decls.append(decl_or_decls) + answer = [] + for decl in decls: + answer.extend(proceed_single(decl)) + return answer + + +def get_global_namespace(decls): + # FIXME: prevent cyclic import + import pygccxml.declarations + found = [ + decl for decl in make_flatten(decls) if decl.name == '::' and + isinstance(decl, pygccxml.declarations.namespace_t)] + if len(found) == 1: + return found[0] + raise RuntimeError("Unable to find global namespace.") + + +def find_all_declarations( + declarations, + type=None, + decl_type=None, + name=None, + parent=None, + recursive=True, + fullname=None): + """ + Returns a list of all declarations that match criteria, defined by + developer. + + For more information about arguments see :class:`match_declaration_t` + class. + + :rtype: [ matched declarations ] + + """ + + if type is not None: + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type + + if recursive: + decls = make_flatten(declarations) + else: + decls = declarations + + return list( + filter( + algorithm.match_declaration_t( + decl_type=decl_type, + name=name, + fullname=fullname, + parent=parent), + decls)) + + +def find_declaration( + declarations, + type=None, + decl_type=None, + name=None, + parent=None, + recursive=True, + fullname=None): + """ + Returns single declaration that match criteria, defined by developer. + If more the one declaration was found None will be returned. + + For more information about arguments see :class:`match_declaration_t` + class. + + :rtype: matched declaration :class:`declaration_t` or None + + """ + if type is not None: + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type + + decl = find_all_declarations( + declarations, + decl_type=decl_type, + name=name, + parent=parent, + recursive=recursive, + fullname=fullname) + if len(decl) == 1: + return decl[0] + + +def find_first_declaration( + declarations, + type=None, + decl_type=None, + name=None, + parent=None, + recursive=True, + fullname=None): + """ + Returns first declaration that match criteria, defined by developer. + + For more information about arguments see :class:`match_declaration_t` + class. + + :rtype: matched declaration :class:`declaration_t` or None + + """ + if type is not None: + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type + + matcher = algorithm.match_declaration_t( + decl_type=decl_type, + name=name, + fullname=fullname, + parent=parent) + if recursive: + decls = make_flatten(declarations) + else: + decls = declarations + for decl in decls: + if matcher(decl): + return decl + return None + + +def declaration_files(decl_or_decls): + """ + Returns set of files + + Every declaration is declared in some file. This function returns set, that + contains all file names of declarations. + + :param decl_or_decls: reference to list of declaration's or single + declaration + :type decl_or_decls: :class:`declaration_t` or [:class:`declaration_t`] + :rtype: set(declaration file names) + + """ + + files = set() + decls = make_flatten(decl_or_decls) + for decl in decls: + if decl.location: + files.add(decl.location.file_name) + return files diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 0f880df0..d49cdb27 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -26,6 +26,7 @@ from . import cpptypes from . import algorithm from . import namespace +from . import scopedef from . import templates from . import enumeration from . import class_declaration @@ -636,7 +637,7 @@ def __init__(self, source, target): self.__target = self.__normalize(target) def __find_class_by_class_declaration(self, class_decl): - found = algorithm.find_declaration( + found = scopedef.find_declaration( class_decl.parent.declarations, name=class_decl.name, decl_type=class_declaration.class_t) @@ -892,7 +893,7 @@ def is_convertible(self): source_inst = source.declaration # class instance could be convertible to something else if it # has operator - casting_operators = algorithm.find_all_declarations( + casting_operators = scopedef.find_all_declarations( source_inst.declarations, decl_type=calldef_members.casting_operator_t, recursive=False) @@ -905,7 +906,7 @@ def is_convertible(self): # is has constructor from source if isinstance(target, cpptypes.declarated_t): if isinstance(target.declaration, class_declaration.class_t): - constructors = algorithm.find_all_declarations( + constructors = scopedef.find_all_declarations( target.declaration.declarations, decl_type=calldef_members.constructor_t, recursive=False) From e112bbd507952e3ffda87d19b7df8a2001a5a854 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 31 May 2016 22:20:29 +0200 Subject: [PATCH 164/268] Move get_global_namespace function to namespace module Now that make flatten is in the scopedef module, the get_global_namespace can logically move to the namespace module. This fixes another cyclic dependency. --- pygccxml/declarations/__init__.py | 5 +++-- pygccxml/declarations/namespace.py | 9 +++++++++ pygccxml/declarations/scopedef.py | 11 ----------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index eec3145f..1c2c8e27 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -17,9 +17,11 @@ from .declaration import declaration_t from .scopedef import scopedef_t from .enumeration import enumeration_t -from .namespace import namespace_t from .typedef import typedef_t +from .namespace import namespace_t +from .namespace import get_global_namespace + from .class_declaration import class_t from .class_declaration import CLASS_TYPES from .class_declaration import ACCESS_TYPES @@ -88,7 +90,6 @@ from .scopedef import find_all_declarations from .scopedef import find_first_declaration from .scopedef import declaration_files -from .scopedef import get_global_namespace from .scopedef import matcher from .algorithm import apply_visitor diff --git a/pygccxml/declarations/namespace.py b/pygccxml/declarations/namespace.py index 8642445b..43c394f9 100644 --- a/pygccxml/declarations/namespace.py +++ b/pygccxml/declarations/namespace.py @@ -270,3 +270,12 @@ def i_depend_on_them(self, recursive=True): for decl in self.declarations: answer.extend(decl.i_depend_on_them()) return answer + + +def get_global_namespace(decls): + found = [ + decl for decl in scopedef.make_flatten(decls) if decl.name == '::' and + isinstance(decl, namespace_t)] + if len(found) == 1: + return found[0] + raise RuntimeError("Unable to find global namespace.") diff --git a/pygccxml/declarations/scopedef.py b/pygccxml/declarations/scopedef.py index 14aada2d..336a263c 100644 --- a/pygccxml/declarations/scopedef.py +++ b/pygccxml/declarations/scopedef.py @@ -1185,17 +1185,6 @@ def proceed_single(decl): return answer -def get_global_namespace(decls): - # FIXME: prevent cyclic import - import pygccxml.declarations - found = [ - decl for decl in make_flatten(decls) if decl.name == '::' and - isinstance(decl, pygccxml.declarations.namespace_t)] - if len(found) == 1: - return found[0] - raise RuntimeError("Unable to find global namespace.") - - def find_all_declarations( declarations, type=None, From a81fa5b4764afeb6b8ec9c7dbd53f6cb2936eacd Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 31 May 2016 23:12:35 +0200 Subject: [PATCH 165/268] Remove unused import --- pygccxml/declarations/type_traits.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index d49cdb27..40b9db31 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -24,7 +24,6 @@ from . import calldef from . import calldef_members from . import cpptypes -from . import algorithm from . import namespace from . import scopedef from . import templates From 9d714664577bf2c7bafed10af331608f8577c413 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 31 May 2016 23:25:25 +0200 Subject: [PATCH 166/268] Move the has_vtable attribute from class declaration to the type_traits module This is now a function, which belongs with the other functions checking if a class has_something. The cyclic import is temporary and will be dropped in 1.9.0, when the property is gone. --- pygccxml/declarations/class_declaration.py | 20 ++++++++++++-------- pygccxml/declarations/type_traits.py | 12 ++++++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 0f3a0378..6e4e1aab 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -12,12 +12,11 @@ - small helper class for describing C++ class hierarchy """ +import warnings from . import scopedef from . import declaration_utils from . import declaration from . import dependencies -from . import calldef_members -from . import calldef_types from . import templates from .. import utils @@ -633,12 +632,17 @@ def find_noncopyable_vars(self): @property def has_vtable(self): """True, if class has virtual table, False otherwise""" - return bool( - self.calldefs( - lambda f: isinstance(f, calldef_members.member_function_t) and - f.virtuality != calldef_types.VIRTUALITY_TYPES.NOT_VIRTUAL, - recursive=False, - allow_empty=True)) + + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The has_vtable argument is deprecated. \n" + + "Please use the has_vtable function from the type_traits \n" + + "module instead.", + DeprecationWarning) + + # prevent cyclic import + from . import type_traits + return type_traits.has_vtable(self) @property def top_class(self): diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 40b9db31..9c07e283 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -23,6 +23,7 @@ from . import matchers from . import calldef from . import calldef_members +from . import calldef_types from . import cpptypes from . import namespace from . import scopedef @@ -480,6 +481,17 @@ def has_public_destructor(type): return d and d.access_type == 'public' +def has_vtable(type_): + """True, if class has virtual table, False otherwise""" + assert(isinstance(type_, class_declaration.class_t)) + return bool( + type_.calldefs( + lambda f: isinstance(f, calldef_members.member_function_t) and + f.virtuality != calldef_types.VIRTUALITY_TYPES.NOT_VIRTUAL, + recursive=False, + allow_empty=True)) + + def is_base_and_derived(based, derived): """returns True, if there is "base and derived" relationship between classes, False otherwise""" From 653c837e46dbeb2a41ff39bc6dd4a83e357685d6 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 31 May 2016 23:45:56 +0200 Subject: [PATCH 167/268] Move the dependency_info_t class to the class_declaration module This class needs things like class_t, moving it to the right module fixes some cyclic import problems This is now possible with the refactoring in the lasts commits. There are still cyclic imports in class_declaration module (type_traits; type_traits_utils) that will need to be checked later --- pygccxml/declarations/__init__.py | 2 +- pygccxml/declarations/calldef.py | 4 +- pygccxml/declarations/class_declaration.py | 105 ++++++++++++++++++- pygccxml/declarations/dependencies.py | 115 --------------------- pygccxml/declarations/typedef.py | 4 +- pygccxml/declarations/variable.py | 3 +- 6 files changed, 109 insertions(+), 124 deletions(-) delete mode 100644 pygccxml/declarations/dependencies.py diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 1c2c8e27..8a7344f8 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -12,7 +12,6 @@ from . import xml_generators as compilers from . import xml_generators -from .dependencies import dependency_info_t from .location import location_t from .declaration import declaration_t from .scopedef import scopedef_t @@ -28,6 +27,7 @@ from .class_declaration import hierarchy_info_t from .class_declaration import class_declaration_t from .class_declaration import class_types +from .class_declaration import dependency_info_t from .cpptypes import type_t from .cpptypes import dummy_type_t diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index 8c1dc488..46d63999 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -20,7 +20,7 @@ from . import cpptypes from . import declaration_utils from . import declaration -from . import dependencies +from . import class_declaration from . import call_invocation from . import type_traits_utils from . import calldef_types @@ -451,7 +451,7 @@ def demangled_name(self): return self.name def _report(self, *args, **keywd): - return dependencies.dependency_info_t(self, *args, **keywd) + return class_declaration.dependency_info_t(self, *args, **keywd) def i_depend_on_them(self, recursive=True): answer = [] diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 6e4e1aab..5eba82c3 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -16,8 +16,8 @@ from . import scopedef from . import declaration_utils from . import declaration -from . import dependencies from . import templates +from . import cpptypes from .. import utils @@ -529,7 +529,7 @@ def i_depend_on_them(self, recursive=True): for base in self.bases: answer.append( - dependencies.dependency_info_t( + dependency_info_t( self, base.related_class, base.access_type, @@ -658,3 +658,104 @@ def top_class(self): return curr class_types = (class_t, class_declaration_t) + + +class impl_details(object): + + @staticmethod + def dig_declarations(depend_on_it): + + # FIXME: prevent cyclic imports + from . import type_traits_utils + + if isinstance(depend_on_it, declaration.declaration_t): + return [depend_on_it] + base_type = type_traits_utils.base_type( + type_traits_utils.remove_alias(depend_on_it)) + if isinstance(base_type, cpptypes.declarated_t): + return [base_type.declaration] + elif isinstance(base_type, cpptypes.calldef_type_t): + result = [] + result.extend(impl_details.dig_declarations(base_type.return_type)) + for argtype in base_type.arguments_types: + result.extend(impl_details.dig_declarations(argtype)) + if isinstance(base_type, cpptypes.member_function_type_t): + result.extend( + impl_details.dig_declarations( + base_type.class_inst)) + return result + return [] + + +class dependency_info_t(object): + + def __init__(self, declaration, depend_on_it, access_type=None, hint=None): + object.__init__(self) + + assert isinstance( + depend_on_it, + (class_t, + cpptypes.type_t)) + self._declaration = declaration + self._depend_on_it = depend_on_it + self._access_type = access_type + self._hint = hint + + @property + def declaration(self): + return self._declaration + # short name + decl = declaration + + @property + def depend_on_it(self): + return self._depend_on_it + + @property + def access_type(self): + return self._access_type + + @access_type.setter + def access_type(self, access_type): + self._access_type = access_type + + def __str__(self): + return 'declaration "%s" depends( %s ) on "%s" ' \ + % (self.declaration, self.access_type, self.depend_on_it) + + @property + def hint(self): + """The declaration, that report dependency can put some additional + inforamtion about dependency. It can be used later""" + return self._hint + + def find_out_depend_on_it_declarations(self): + """If declaration depends on other declaration and not on some type + this function will return reference to it. Otherwise None will be + returned + """ + return impl_details.dig_declarations(self.depend_on_it) + + @staticmethod + def i_depend_on_them(decl): + """Returns set of declarations. every item in the returned set, + depends on a declaration from the input""" + + to_be_included = set() + for dependency_info in decl.i_depend_on_them(): + for ddecl in dependency_info.find_out_depend_on_it_declarations(): + if ddecl: + to_be_included.add(ddecl) + + if isinstance(decl.parent, class_t): + to_be_included.add(decl.parent) + return to_be_included + + @staticmethod + def we_depend_on_them(decls): + """Returns set of declarations. every item in the returned set, + depends on a declaration from the input""" + to_be_included = set() + for decl in decls: + to_be_included.update(dependency_info_t.i_depend_on_them(decl)) + return to_be_included diff --git a/pygccxml/declarations/dependencies.py b/pygccxml/declarations/dependencies.py deleted file mode 100644 index 85ecc934..00000000 --- a/pygccxml/declarations/dependencies.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright 2014-2016 Insight Software Consortium. -# Copyright 2004-2008 Roman Yakovenko. -# Distributed under the Boost Software License, Version 1.0. -# See http://www.boost.org/LICENSE_1_0.txt - -""" -this module contains class that keeps dependency information of some -declaration - -""" - -from . import cpptypes -from . import declaration - - -class impl_details(object): - - @staticmethod - def dig_declarations(depend_on_it): - - # FIXME: prevent cyclic imports - from . import type_traits_utils - - if isinstance(depend_on_it, declaration.declaration_t): - return [depend_on_it] - base_type = type_traits_utils.base_type( - type_traits_utils.remove_alias(depend_on_it)) - if isinstance(base_type, cpptypes.declarated_t): - return [base_type.declaration] - elif isinstance(base_type, cpptypes.calldef_type_t): - result = [] - result.extend(impl_details.dig_declarations(base_type.return_type)) - for argtype in base_type.arguments_types: - result.extend(impl_details.dig_declarations(argtype)) - if isinstance(base_type, cpptypes.member_function_type_t): - result.extend( - impl_details.dig_declarations( - base_type.class_inst)) - return result - return [] - - -class dependency_info_t(object): - - def __init__(self, declaration, depend_on_it, access_type=None, hint=None): - object.__init__(self) - # FIXME: prevent cyclic import - from . import class_declaration - assert isinstance( - depend_on_it, - (class_declaration.class_t, - cpptypes.type_t)) - self._declaration = declaration - self._depend_on_it = depend_on_it - self._access_type = access_type - self._hint = hint - - @property - def declaration(self): - return self._declaration - # short name - decl = declaration - - @property - def depend_on_it(self): - return self._depend_on_it - - @property - def access_type(self): - return self._access_type - - @access_type.setter - def access_type(self, access_type): - self._access_type = access_type - - def __str__(self): - return 'declaration "%s" depends( %s ) on "%s" ' \ - % (self.declaration, self.access_type, self.depend_on_it) - - @property - def hint(self): - """The declaration, that report dependency can put some additional - inforamtion about dependency. It can be used later""" - return self._hint - - def find_out_depend_on_it_declarations(self): - """If declaration depends on other declaration and not on some type - this function will return reference to it. Otherwise None will be - returned - """ - return impl_details.dig_declarations(self.depend_on_it) - - @staticmethod - def i_depend_on_them(decl): - """Returns set of declarations. every item in the returned set, - depends on a declaration from the input""" - from . import class_declaration # FIXME: prevent cyclic imports - to_be_included = set() - for dependency_info in decl.i_depend_on_them(): - for ddecl in dependency_info.find_out_depend_on_it_declarations(): - if ddecl: - to_be_included.add(ddecl) - - if isinstance(decl.parent, class_declaration.class_t): - to_be_included.add(decl.parent) - return to_be_included - - @staticmethod - def we_depend_on_them(decls): - """Returns set of declarations. every item in the returned set, - depends on a declaration from the input""" - to_be_included = set() - for decl in decls: - to_be_included.update(dependency_info_t.i_depend_on_them(decl)) - return to_be_included diff --git a/pygccxml/declarations/typedef.py b/pygccxml/declarations/typedef.py index 485e186f..c0b1bc2c 100644 --- a/pygccxml/declarations/typedef.py +++ b/pygccxml/declarations/typedef.py @@ -9,7 +9,7 @@ import warnings from . import declaration -from . import dependencies +from . import class_declaration class typedef_t(declaration.declaration_t): @@ -80,7 +80,7 @@ def decl_type(self, decl_type): self._decl_type = decl_type def i_depend_on_them(self, recursive=True): - return [dependencies.dependency_info_t(self, self.decl_type)] + return [class_declaration.dependency_info_t(self, self.decl_type)] @property def byte_size(self): diff --git a/pygccxml/declarations/variable.py b/pygccxml/declarations/variable.py index f5e96898..334c8485 100644 --- a/pygccxml/declarations/variable.py +++ b/pygccxml/declarations/variable.py @@ -9,7 +9,6 @@ import warnings from . import declaration -from . import dependencies from . import class_declaration @@ -157,7 +156,7 @@ def mangled(self, mangled): self._mangled = mangled def i_depend_on_them(self, recursive=True): - return [dependencies.dependency_info_t(self, self.decl_type)] + return [class_declaration.dependency_info_t(self, self.decl_type)] def get_mangled_name(self): if not self._mangled and not self._demangled \ From f6cf7e9662734432e23d98e1ac7caece4e590a26 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 2 Jun 2016 23:59:12 +0200 Subject: [PATCH 168/268] Move is_copy_constructor and is_trivial_constructor to the type_traits module This is their place, with all the other is_sth() methods. This allows to keep the different member_calldef_t classes (like constructor_t) small. For this, the attributes are deprecated and will be removed in 1.9.0. --- pygccxml/declarations/__init__.py | 1 + pygccxml/declarations/calldef_members.py | 24 +++++++++++++++--- pygccxml/declarations/type_traits.py | 31 +++++++++++++++++++++--- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 8a7344f8..57f33649 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -150,6 +150,7 @@ from .type_traits import is_std_wostream from .type_traits import is_calldef_pointer from .type_traits import is_copy_constructor +from .type_traits import is_trivial_constructor from .type_traits import is_unary_operator from .type_traits import is_binary_operator diff --git a/pygccxml/declarations/calldef_members.py b/pygccxml/declarations/calldef_members.py index d48c9cd1..024cfe54 100644 --- a/pygccxml/declarations/calldef_members.py +++ b/pygccxml/declarations/calldef_members.py @@ -3,6 +3,7 @@ # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt +import warnings from . import calldef from . import declaration_utils from . import cpptypes @@ -195,13 +196,30 @@ def is_copy_constructor(self): """ - # FIXME: prevent cyclic dependencies + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The is_copy_constructor attribute is deprecated. \n" + + "Please use the is_copy_constructor function from the \n" + + "type_traits module instead.", + DeprecationWarning) + + # prevent cyclic dependencies from . import type_traits - return type_traits.is_copy_constructor(self.arguments, self.parent) + return type_traits.is_copy_constructor(self) @property def is_trivial_constructor(self): - return not bool(self.arguments) + + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The is_trivial_constructor attribute is deprecated. \n" + + "Please use the is_trivial_constructor function from the \n" + + "type_traits module instead.", + DeprecationWarning) + + # prevent cyclic dependencies + from . import type_traits + return type_traits.is_trivial_constructor(self) class destructor_t(member_calldef_t): diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 9c07e283..6074de89 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -1304,12 +1304,21 @@ def is_std_wostream(type_): return remove_cv(type_).decl_string in wostream_equivalences -def is_copy_constructor(args, parent): +def is_copy_constructor(constructor): """ - Returns True if described declaration is copy constructor, - otherwise False. + Check if the declaration is a copy constructor, + + Args: + constructor (declarations.constructor_t): the constructor + to be checked. + + Returns: + bool: True if this is a copy constructor, False instead. """ + assert (isinstance(constructor, calldef_members.constructor_t)) + args = constructor.arguments + parent = constructor.parent # A copy constructor has only one argument if len(args) != 1: @@ -1349,3 +1358,19 @@ def is_copy_constructor(args, parent): # Final check: compare the parent (the class declaration for example) # with the declaration of the type passed as argument. return id(un_aliased.base.declaration) == id(parent) + + +def is_trivial_constructor(constructor): + """ + Check if the declaration is a trivial constructor. + + Args: + constructor (declarations.constructor_t): the constructor + to be checked. + + Returns: + bool: True if this is a trivial constructor, False instead. + + """ + assert(isinstance(constructor, calldef_members.constructor_t)) + return not bool(constructor.arguments) From b06bc0886c04000c45550c8baf78f411ed2bbf06 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 4 Jun 2016 16:47:02 +0200 Subject: [PATCH 169/268] Move the find_copy_constructor and find_trivial_constructor to the type_traits module In fact, there was already a find_trivial_constructor function in the type_traits module, so this makes the situation cleaner by providing only one way to do things. Deprecate the find_copy_constructor and find_trivial_constructor methods from class_t Do not print information about copy constructors for constructor_t (this is a side-effect of the changes). That information would be nice to have, but not necessary. --- pygccxml/declarations/__init__.py | 1 + pygccxml/declarations/calldef_members.py | 2 - pygccxml/declarations/class_declaration.py | 36 ++++++++------- pygccxml/declarations/decl_printer.py | 3 +- pygccxml/declarations/type_traits.py | 54 ++++++++++++++++++---- unittests/declarations_tester.py | 2 +- unittests/test_copy_constructor.py | 10 ++-- 7 files changed, 75 insertions(+), 33 deletions(-) diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 57f33649..5524a437 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -175,6 +175,7 @@ from .type_traits import has_public_constructor from .type_traits import has_trivial_constructor from .type_traits import find_trivial_constructor +from .type_traits import find_copy_constructor from .type_traits import has_public_binary_operator from .type_traits import has_any_non_copyconstructor diff --git a/pygccxml/declarations/calldef_members.py b/pygccxml/declarations/calldef_members.py index 024cfe54..7126fbbe 100644 --- a/pygccxml/declarations/calldef_members.py +++ b/pygccxml/declarations/calldef_members.py @@ -184,8 +184,6 @@ def __str__(self): res = "%s(%s)" % (name, ", ".join(args)) # Append the declaration class cls = 'constructor' - if self.is_copy_constructor: - cls = 'copy ' + cls return "%s [%s]" % (res, cls) @property diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 5eba82c3..12d6c78c 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -552,24 +552,28 @@ def container_traits(self): return self._container_traits def find_copy_constructor(self): - copy_ = self.constructors( - lambda x: x.is_copy_constructor, - recursive=False, - allow_empty=True) - if copy_: - return copy_[0] - else: - return None + + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The find_copy_constructor method is deprecated. \n" + + "Please use the find_copy_constructor function from the" + "type_traits module instead.", + DeprecationWarning) + + from . import type_traits # prevent cyclic dependencies + return type_traits.find_copy_constructor(self) def find_trivial_constructor(self): - trivial = self.constructors( - lambda x: x.is_trivial_constructor, - recursive=False, - allow_empty=True) - if trivial: - return trivial[0] - else: - return None + + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The find_trivial_constructor method is deprecated. \n" + + "Please use the find_trivial_constructor function from the" + "type_traits module instead.", + DeprecationWarning) + + from . import type_traits # prevent cyclic dependencies + return type_traits.find_trivial_constructor(self) def _get_partial_name_impl(self): from . import type_traits # prevent cyclic dependencies diff --git a/pygccxml/declarations/decl_printer.py b/pygccxml/declarations/decl_printer.py index 1fe00e95..26bf0600 100644 --- a/pygccxml/declarations/decl_printer.py +++ b/pygccxml/declarations/decl_printer.py @@ -15,6 +15,7 @@ from . import decl_visitor from . import variable_t from . import calldef_t +from . import type_traits from .. import utils @@ -243,7 +244,7 @@ def visit_constructor(self): if self.__print_details: self.writer(indent + 'copy constructor: ' + - str(self.__inst.is_copy_constructor) + + str(type_traits.is_copy_constructor(self.__inst)) + os.linesep) def visit_destructor(self): diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 6074de89..688f0d16 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -418,16 +418,54 @@ def get_declaration(self, type_): def find_trivial_constructor(type_): - """returns reference to trivial constructor or None""" + """ + Returns reference to trivial constructor. + + Args: + type_ (declarations.class_t): the class to be searched. + + Returns: + declarations.constructor_t: the trivial constructor + + """ assert isinstance(type_, class_declaration.class_t) - return type_.find_trivial_constructor() + + trivial = type_.constructors( + lambda x: is_trivial_constructor(x), + recursive=False, + allow_empty=True) + if trivial: + return trivial[0] + else: + return None + + +def find_copy_constructor(type_): + """ + Returns reference to copy constructor. + + Args: + type_ (declarations.class_t): the class to be searched. + + Returns: + declarations.constructor_t: the copy constructor + + """ + copy_ = type_.constructors( + lambda x: is_copy_constructor(x), + recursive=False, + allow_empty=True) + if copy_: + return copy_[0] + else: + return None def has_trivial_constructor(class_): """if class has public trivial constructor, this function will return reference to it, None otherwise""" class_ = class_traits.get_declaration(class_) - trivial = class_.find_trivial_constructor() + trivial = find_trivial_constructor(class_) if trivial and trivial.access_type == 'public': return trivial @@ -436,7 +474,7 @@ def has_copy_constructor(class_): """if class has public copy constructor, this function will return reference to it, None otherwise""" class_ = class_traits.get_declaration(class_) - copy_constructor = class_.find_copy_constructor() + copy_constructor = find_copy_constructor(class_) if copy_constructor and copy_constructor.access_type == 'public': return copy_constructor @@ -458,7 +496,7 @@ def has_public_constructor(class_): them, otherwise None""" class_ = class_traits.get_declaration(class_) decls = class_.constructors( - lambda c: not c.is_copy_constructor and c.access_type == 'public', + lambda c: not is_copy_constructor(c) and c.access_type == 'public', recursive=False, allow_empty=True) if decls: @@ -515,7 +553,7 @@ def has_any_non_copyconstructor(type): this function will return list of them, otherwise None""" class_ = class_traits.get_declaration(type) decls = class_.constructors( - lambda c: not c.is_copy_constructor and c.access_type == 'public', + lambda c: not is_copy_constructor(c) and c.access_type == 'public', recursive=False, allow_empty=True) if decls: @@ -985,7 +1023,7 @@ def is_noncopyable(class_): # if class has public, user defined copy constructor, than this class is # copyable - copy_ = class_decl.find_copy_constructor() + copy_ = find_copy_constructor(class_decl) if copy_ and copy_.access_type == 'public' and not copy_.is_artificial: return False @@ -999,7 +1037,7 @@ def is_noncopyable(class_): if not has_copy_constructor(base_desc.related_class): - base_copy_ = base_desc.related_class.find_copy_constructor() + base_copy_ = find_copy_constructor(base_desc.related_class) if base_copy_: diff --git a/unittests/declarations_tester.py b/unittests/declarations_tester.py index a4bdcc43..5d523259 100644 --- a/unittests/declarations_tester.py +++ b/unittests/declarations_tester.py @@ -206,7 +206,7 @@ def test_constructors_destructors(self): error_text = "copy constructor has not been found" self.assertTrue(1 == len( [constructor for constructor in constructor_found if - constructor.is_copy_constructor]), error_text) + declarations.is_copy_constructor(constructor)]), error_text) # there is nothing to check about constructors - I know the # implementation of parser. # In this case it doesn't different from any other function diff --git a/unittests/test_copy_constructor.py b/unittests/test_copy_constructor.py index 558ec35c..31e95521 100644 --- a/unittests/test_copy_constructor.py +++ b/unittests/test_copy_constructor.py @@ -35,11 +35,11 @@ def test(self): ctors.append(decl) # test::test(test const & t0) [copy constructor] - self.assertTrue(ctors[0].is_copy_constructor) + self.assertTrue(declarations.is_copy_constructor(ctors[0])) # test::test(float const & t0) [constructor] - self.assertFalse(ctors[1].is_copy_constructor) + self.assertFalse(declarations.is_copy_constructor(ctors[1])) # test::test(myvar t0) [constructor] - self.assertFalse(ctors[2].is_copy_constructor) + self.assertFalse(declarations.is_copy_constructor(ctors[2])) t2class = self.global_ns.class_("test2") ctors = [] @@ -56,9 +56,9 @@ def test(self): positions = [1, 0] # test2::test2() [constructor] - self.assertFalse(ctors[positions[0]].is_copy_constructor) + self.assertFalse(declarations.is_copy_constructor(ctors[positions[0]])) # test2::test2(test2 const & arg0) [copy constructor] - self.assertTrue(ctors[positions[1]].is_copy_constructor) + self.assertTrue(declarations.is_copy_constructor(ctors[positions[1]])) def create_suite(): From e01afa1ef8d30770c8234d699b86b959005ca1c0 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 4 Jun 2016 16:51:37 +0200 Subject: [PATCH 170/268] Documentation: the mentioned methods are in the declarations module I should only refer to the public API for the users --- pygccxml/declarations/calldef_members.py | 4 ++-- pygccxml/declarations/class_declaration.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pygccxml/declarations/calldef_members.py b/pygccxml/declarations/calldef_members.py index 7126fbbe..94a22acb 100644 --- a/pygccxml/declarations/calldef_members.py +++ b/pygccxml/declarations/calldef_members.py @@ -198,7 +198,7 @@ def is_copy_constructor(self): warnings.warn( "The is_copy_constructor attribute is deprecated. \n" + "Please use the is_copy_constructor function from the \n" + - "type_traits module instead.", + "declarations module instead.", DeprecationWarning) # prevent cyclic dependencies @@ -212,7 +212,7 @@ def is_trivial_constructor(self): warnings.warn( "The is_trivial_constructor attribute is deprecated. \n" + "Please use the is_trivial_constructor function from the \n" + - "type_traits module instead.", + "declarations module instead.", DeprecationWarning) # prevent cyclic dependencies diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 12d6c78c..5cf9172c 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -557,7 +557,7 @@ def find_copy_constructor(self): warnings.warn( "The find_copy_constructor method is deprecated. \n" + "Please use the find_copy_constructor function from the" - "type_traits module instead.", + "declarations module instead.", DeprecationWarning) from . import type_traits # prevent cyclic dependencies @@ -569,7 +569,7 @@ def find_trivial_constructor(self): warnings.warn( "The find_trivial_constructor method is deprecated. \n" + "Please use the find_trivial_constructor function from the" - "type_traits module instead.", + "declarations module instead.", DeprecationWarning) from . import type_traits # prevent cyclic dependencies @@ -640,7 +640,7 @@ def has_vtable(self): # Deprecated since 1.8.0. Will be removed in 1.9.0 warnings.warn( "The has_vtable argument is deprecated. \n" + - "Please use the has_vtable function from the type_traits \n" + + "Please use the has_vtable function from the declarations \n" + "module instead.", DeprecationWarning) From 0190f38db28bb1f3a40b2a9283ece6763a17349d Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 4 Jun 2016 17:02:11 +0200 Subject: [PATCH 171/268] Move the find_noncopyable_vars method to the type_traits module The old method is deprecated. The cyclic dependency will be fixed once the deprecated method is removed. --- pygccxml/declarations/__init__.py | 1 + pygccxml/declarations/class_declaration.py | 54 ++++---------------- pygccxml/declarations/type_traits.py | 58 +++++++++++++++++++++- 3 files changed, 67 insertions(+), 46 deletions(-) diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 5524a437..45103cda 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -176,6 +176,7 @@ from .type_traits import has_trivial_constructor from .type_traits import find_trivial_constructor from .type_traits import find_copy_constructor +from .type_traits import find_noncopyable_vars from .type_traits import has_public_binary_operator from .type_traits import has_any_non_copyconstructor diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 5cf9172c..4bc50e21 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -587,51 +587,15 @@ def _get_partial_name_impl(self): def find_noncopyable_vars(self): """returns list of all `noncopyable` variables""" - from . import type_traits as tt # prevent cyclic dependencies - - logger = utils.loggers.cxx_parser - mvars = self.variables( - lambda v: not v.type_qualifiers.has_static, - recursive=False, - allow_empty=True) - noncopyable_vars = [] - - message = ( - "__contains_noncopyable_mem_var - %s - TRUE - " + - "containes const member variable") - - for mvar in mvars: - - type_ = tt.remove_reference(mvar.decl_type) - - if tt.is_const(type_): - no_const = tt.remove_const(type_) - if tt.is_fundamental(no_const) or tt.is_enum(no_const): - logger.debug(( - message + "- fundamental or enum") - % self.decl_string) - noncopyable_vars.append(mvar) - if tt.is_class(no_const): - logger.debug((message + " - class") % self.decl_string) - noncopyable_vars.append(mvar) - if tt.is_array(no_const): - logger.debug((message + " - array") % self.decl_string) - noncopyable_vars.append(mvar) - - if tt.class_traits.is_my_case(type_): - - cls = tt.class_traits.get_declaration(type_) - if tt.is_noncopyable(cls): - logger.debug(( - message + " - class that is not copyable") - % self.decl_string) - noncopyable_vars.append(mvar) - - logger.debug(( - "__contains_noncopyable_mem_var - %s - FALSE - doesn't " + - "contain noncopyable members") % self.decl_string) - - return noncopyable_vars + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The find_noncopyable_vars method is deprecated. \n" + + "Please use the find_noncopyable_vars function from the" + "declarations module instead.", + DeprecationWarning) + + from . import type_traits # prevent cyclic dependencies + type_traits.find_noncopyable_vars(self) @property def has_vtable(self): diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 688f0d16..b31079f9 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -461,6 +461,62 @@ def find_copy_constructor(type_): return None +def find_noncopyable_vars(type_): + """ + Returns list of all `noncopyable` variables. + + Args: + type_ (declarations.class_t): the class to be searched. + + Returns: + list: list of all `noncopyable` variables. + + """ + assert(isinstance(type_, class_declaration.class_t)) + + logger = utils.loggers.cxx_parser + mvars = type_.variables( + lambda v: not v.type_qualifiers.has_static, + recursive=False, + allow_empty=True) + noncopyable_vars = [] + + message = ( + "__contains_noncopyable_mem_var - %s - TRUE - " + + "contains const member variable") + + for mvar in mvars: + + type_ = remove_reference(mvar.decl_type) + + if is_const(type_): + no_const = remove_const(type_) + if is_fundamental(no_const) or is_enum(no_const): + logger.debug((message + "- fundamental or enum") + % type_.decl_string) + noncopyable_vars.append(mvar) + if is_class(no_const): + logger.debug((message + " - class") % type_.decl_string) + noncopyable_vars.append(mvar) + if is_array(no_const): + logger.debug((message + " - array") % type_.decl_string) + noncopyable_vars.append(mvar) + + if class_traits.is_my_case(type_): + + cls = class_traits.get_declaration(type_) + if is_noncopyable(cls): + logger.debug((message + " - class that is not copyable") + % type_.decl_string) + noncopyable_vars.append(mvar) + + logger.debug( + ("__contains_noncopyable_mem_var - %s - FALSE - doesn't " + + "contain noncopyable members") % type_.decl_string) + + return noncopyable_vars + + def has_trivial_constructor(class_): """if class has public trivial constructor, this function will return reference to it, None otherwise""" @@ -994,7 +1050,7 @@ def __is_noncopyable_single(class_): " public destructor: yes"]) logger.debug(msg) return False - if class_.find_noncopyable_vars(): + if find_noncopyable_vars(class_): logger.debug( ("__is_noncopyable_single(TRUE) - %s - contains noncopyable " + "members") % class_.decl_string) From 769900addbc8b18f1a22c992cd2c767e74e4d007 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 6 Jun 2016 21:35:25 +0200 Subject: [PATCH 172/268] Move all matchers that depend on the declaration modules to a separate module This allows to load the basic matcher_base_t and some of it's subclasses without importing everything --- pygccxml/declarations/__init__.py | 13 +- .../declarations/declarations_matchers.py | 421 ++++++++++++++++ pygccxml/declarations/matchers.py | 456 +----------------- 3 files changed, 449 insertions(+), 441 deletions(-) create mode 100644 pygccxml/declarations/declarations_matchers.py diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 45103cda..4af550a8 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -221,16 +221,17 @@ from .matchers import or_matcher_t from .matchers import and_matcher_t from .matchers import not_matcher_t -from .matchers import declaration_matcher_t -from .matchers import calldef_matcher_t -from .matchers import namespace_matcher_t -from .matchers import variable_matcher_t from .matchers import regex_matcher_t -from .matchers import access_type_matcher_t -from .matchers import operator_matcher_t from .matchers import custom_matcher_t +from .matchers import access_type_matcher_t from .matchers import virtuality_type_matcher_t +from .declarations_matchers import declaration_matcher_t +from .declarations_matchers import calldef_matcher_t +from .declarations_matchers import namespace_matcher_t +from .declarations_matchers import variable_matcher_t +from .declarations_matchers import operator_matcher_t + from .mdecl_wrapper import mdecl_wrapper_t from .decl_printer import decl_printer_t diff --git a/pygccxml/declarations/declarations_matchers.py b/pygccxml/declarations/declarations_matchers.py new file mode 100644 index 00000000..8a2015ba --- /dev/null +++ b/pygccxml/declarations/declarations_matchers.py @@ -0,0 +1,421 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +import os +import warnings + +from . import templates +from . import declaration_utils +from . import matcher_base_t +from . import variable +from . import cpptypes +from . import namespace +from . import calldef +from . import calldef_members +from .. import utils + + +class declaration_matcher_t(matcher_base_t): + + """ + Instance of this class will match declarations by next criteria: + - declaration name, also could be fully qualified name + Example: `wstring` or `::std::wstring` + - declaration type + Example: :class:`class_t`, :class:`namespace_t`, + :class:`enumeration_t` + - location within file system ( file or directory ) + """ + + def __init__( + self, + name=None, + decl_type=None, + header_dir=None, + header_file=None): + """ + :param decl_type: declaration type to match by. For example + :class:`enumeration_t`. + :type decl_type: any class that derives from :class:`declaration_t` + class + + :param name: declaration name, could be full name. + :type name: str + + :param header_dir: absolute directory path + :type header_dir: str + + :param header_file: absolute file path + :type header_file: str + + """ + # An other option is that pygccxml will create absolute path using + # os.path.abspath function. But I think this is just wrong, because + # abspath builds path using current working directory. This behavior + # is fragile and very difficult to find a bug. + matcher_base_t.__init__(self) + self.decl_type = decl_type + self.__name = None + self.__opt_is_tmpl_inst = None + self.__opt_tmpl_name = None + self.__opt_is_full_name = None + self.__decl_name_only = None + + # Set the name through the setter. + self.name = name + + self.header_dir = header_dir + self.header_file = header_file + + if self.header_dir: + self.header_dir = utils.normalize_path(self.header_dir) + if not os.path.isabs(self.header_dir): + raise RuntimeError( + "Path to header directory should be absolute!") + + if self.header_file: + self.header_file = utils.normalize_path(self.header_file) + if not os.path.isabs(self.header_file): + raise RuntimeError("Path to header file should be absolute!") + + @property + def name(self): + return self.__name + + @name.setter + def name(self, name): + self.__name = name + if not self.__name: + self.__opt_is_tmpl_inst = None + self.__opt_tmpl_name = None + self.__opt_is_full_name = None + self.__decl_name_only = None + else: + self.__opt_is_tmpl_inst = templates.is_instantiation(self.__name) + self.__opt_tmpl_name = templates.name(self.__name) + if self.__opt_is_tmpl_inst: + if '::' in self.__opt_tmpl_name: + self.__opt_is_full_name = True + self.__decl_name_only = \ + self.__opt_tmpl_name.split('::')[-1] + else: + self.__opt_is_full_name = False + self.__decl_name_only = self.__opt_tmpl_name + self.__name = templates.normalize(name) + else: + if '::' in self.__name: + self.__opt_is_full_name = True + self.__decl_name_only = self.__name.split('::')[-1] + else: + self.__opt_is_full_name = False + self.__decl_name_only = self.__name + + def __str__(self): + msg = [] + if self.decl_type is not None: + msg.append('(decl type==%s)' % self.decl_type.__name__) + if self.name is not None: + msg.append('(name==%s)' % self.name) + if self.header_dir is not None: + msg.append('(header dir==%s)' % self.header_dir) + if self.header_file is not None: + msg.append('(header file==%s)' % self.header_file) + if not msg: + msg.append('any') + return ' and '.join(msg) + + def __call__(self, decl): + if self.decl_type is not None: + if not isinstance(decl, self.decl_type): + return False + if self.name is not None: + if not self.check_name(decl): + return False + if self.header_dir is not None: + if decl.location: + decl_dir = os.path.abspath( + os.path.dirname(decl.location.file_name)) + decl_dir = utils.normalize_path(decl_dir) + if decl_dir[:len(self.header_dir)] != self.header_dir: + return False + else: + return False + if self.header_file is not None: + if decl.location: + decl_file = os.path.abspath(decl.location.file_name) + decl_file = utils.normalize_path(decl_file) + if decl_file != self.header_file: + return False + else: + return False + return True + + def check_name(self, decl): + assert self.name is not None + if self.__opt_is_tmpl_inst: + if not self.__opt_is_full_name: + if self.name != templates.normalize(decl.name) \ + and self.name != templates.normalize(decl.partial_name): + return False + else: + if self.name != templates.normalize( + declaration_utils.full_name( + decl, with_defaults=True)) \ + and self.name != templates.normalize( + declaration_utils.full_name( + decl, with_defaults=False)): + return False + else: + if not self.__opt_is_full_name: + if self.name != decl.name and self.name != decl.partial_name: + return False + else: + if self.name != declaration_utils.full_name( + decl, with_defaults=True) \ + and self.name != declaration_utils.full_name( + decl, with_defaults=False): + return False + return True + + def is_full_name(self): + return self.__opt_is_full_name + + @property + def decl_name_only(self): + return self.__decl_name_only + + +class variable_matcher_t(declaration_matcher_t): + + """ + Instance of this class will match variables by next criteria: + - :class:`declaration_matcher_t` criteria + - variable type. Example: :class:`int_t` or 'int' + """ + + def __init__( + self, + name=None, + type=None, + decl_type=None, + header_dir=None, + header_file=None): + """ + :param decl_type: variable type + :type decl_type: string or instance of :class:`type_t` derived class + """ + + if type is not None: + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The type argument is deprecated. \n" + + "Please use the decl_type argument instead.", + DeprecationWarning) + if decl_type is not None: + raise ( + "Please use only either the type or " + + "decl_type argument.") + # Still allow to use the old type for the moment. + decl_type = type + + declaration_matcher_t.__init__( + self, + name=name, + decl_type=variable.variable_t, + header_dir=header_dir, + header_file=header_file) + self._decl_type = decl_type + + def __call__(self, decl): + if not super(variable_matcher_t, self).__call__(decl): + return False + if self._decl_type is not None: + if isinstance(self._decl_type, cpptypes.type_t): + if self._decl_type != decl.decl_type: + return False + else: + if self._decl_type != decl.decl_type.decl_string: + return False + return True + + def __str__(self): + msg = [super(variable_matcher_t, self).__str__()] + if msg == ['any']: + msg = [] + if self._decl_type is not None: + msg.append('(value type==%s)' % str(self._decl_type)) + if not msg: + msg.append('any') + return ' and '.join(msg) + + +class namespace_matcher_t(declaration_matcher_t): + + """Instance of this class will match namespaces by name.""" + + def __init__(self, name=None): + declaration_matcher_t.__init__( + self, + name=name, + decl_type=namespace.namespace_t) + + def __call__(self, decl): + if self.name and decl.name == '': + # unnamed namespace have same name as thier parent, we should + # prevent this happens. The price is: user should search for + # unnamed namespace directly. + return False + return super(namespace_matcher_t, self).__call__(decl) + + +class calldef_matcher_t(declaration_matcher_t): + + """ + Instance of this class will match callable by the following criteria: + * :class:`declaration_matcher_t` criteria + * return type. For example: :class:`int_t` or 'int' + * argument types + + """ + + def __init__( + self, + name=None, + return_type=None, + arg_types=None, + decl_type=None, + header_dir=None, + header_file=None): + """ + :param return_type: callable return type + :type return_type: string or instance of :class:`type_t` derived class + + :type arg_types: list + :param arg_types: list of function argument types. `arg_types` can + contain. + Any item within the list could be string or instance + of :class:`type_t` derived class. If you don't want + some argument to participate in match you can put + None. + + For example: + + .. code-block:: python + + calldef_matcher_t( arg_types=[ 'int &', None ] ) + + will match all functions that takes 2 arguments, where the first one is + reference to integer and second any + """ + if None is decl_type: + decl_type = calldef.calldef_t + declaration_matcher_t.__init__( + self, + name=name, + decl_type=decl_type, + header_dir=header_dir, + header_file=header_file) + + self.return_type = return_type + self.arg_types = arg_types + + def __call__(self, decl): + if not super(calldef_matcher_t, self).__call__(decl): + return False + if self.return_type is not None \ + and not self.__compare_types(self.return_type, decl.return_type): + return False + if self.arg_types: + if isinstance(self.arg_types, (list, tuple)): + if len(self.arg_types) != len(decl.arguments): + return False + for type_or_str, arg in zip(self.arg_types, decl.arguments): + if type_or_str is None: + continue + else: + if not self.__compare_types( + type_or_str, arg.decl_type): + return False + return True + + def __compare_types(self, type_or_str, type): + assert type_or_str + if type is None: + return False + if isinstance(type_or_str, cpptypes.type_t): + if type_or_str != type: + return False + else: + if type_or_str != type.decl_string: + return False + return True + + def __str__(self): + msg = [super(calldef_matcher_t, self).__str__()] + if msg == ['any']: + msg = [] + if self.return_type is not None: + msg.append('(return type==%s)' % str(self.return_type)) + if self.arg_types: + for i, arg_type in enumerate(self.arg_types): + if arg_type is None: + msg.append('(arg %d type==any)' % i) + else: + msg.append('(arg %d type==%s)' % (i, str(arg_type))) + if not msg: + msg.append('any') + return ' and '.join(msg) + + +class operator_matcher_t(calldef_matcher_t): + + """ + Instance of this class will match operators by next criteria: + * :class:`calldef_matcher_t` criteria + * operator symbol: =, !=, (), [] and etc + """ + + def __init__( + self, + name=None, + symbol=None, + return_type=None, + arg_types=None, + decl_type=None, + header_dir=None, + header_file=None): + """ + :param symbol: operator symbol + :type symbol: str + """ + if None is decl_type: + decl_type = calldef_members.operator_t + calldef_matcher_t.__init__( + self, + name=name, + return_type=return_type, + arg_types=arg_types, + decl_type=decl_type, + header_dir=header_dir, + header_file=header_file) + self.symbol = symbol + + def __call__(self, decl): + if not super(operator_matcher_t, self).__call__(decl): + return False + if self.symbol is not None: + if self.symbol != decl.symbol: + return False + return True + + def __str__(self): + msg = [super(operator_matcher_t, self).__str__()] + if msg == ['any']: + msg = [] + if self.symbol is not None: + msg.append('(symbol==%s)' % str(self.symbol)) + if not msg: + msg.append('any') + return ' and '.join(msg) diff --git a/pygccxml/declarations/matchers.py b/pygccxml/declarations/matchers.py index eb53a720..0dd1dbd2 100644 --- a/pygccxml/declarations/matchers.py +++ b/pygccxml/declarations/matchers.py @@ -8,18 +8,8 @@ functionality according to some criteria """ -import os import re -import warnings -from . import declaration_utils -from . import variable -from . import namespace -from . import calldef -from . import calldef_members -from . import cpptypes -from . import templates from . import class_declaration -from pygccxml import utils class matcher_base_t(object): @@ -128,410 +118,6 @@ def __str__(self): return "~(%s)" % str(self.matcher) -class declaration_matcher_t(matcher_base_t): - - """ - Instance of this class will match declarations by next criteria: - - declaration name, also could be fully qualified name - Example: `wstring` or `::std::wstring` - - declaration type - Example: :class:`class_t`, :class:`namespace_t`, - :class:`enumeration_t` - - location within file system ( file or directory ) - """ - - def __init__( - self, - name=None, - decl_type=None, - header_dir=None, - header_file=None): - """ - :param decl_type: declaration type to match by. For example - :class:`enumeration_t`. - :type decl_type: any class that derives from :class:`declaration_t` - class - - :param name: declaration name, could be full name. - :type name: str - - :param header_dir: absolute directory path - :type header_dir: str - - :param header_file: absolute file path - :type header_file: str - - """ - # An other option is that pygccxml will create absolute path using - # os.path.abspath function. But I think this is just wrong, because - # abspath builds path using current working directory. This behavior - # is fragile and very difficult to find a bug. - matcher_base_t.__init__(self) - self.decl_type = decl_type - self.__name = None - self.__opt_is_tmpl_inst = None - self.__opt_tmpl_name = None - self.__opt_is_full_name = None - self.__decl_name_only = None - - # Set the name through the setter. - self.name = name - - self.header_dir = header_dir - self.header_file = header_file - - if self.header_dir: - self.header_dir = utils.normalize_path(self.header_dir) - if not os.path.isabs(self.header_dir): - raise RuntimeError( - "Path to header directory should be absolute!") - - if self.header_file: - self.header_file = utils.normalize_path(self.header_file) - if not os.path.isabs(self.header_file): - raise RuntimeError("Path to header file should be absolute!") - - @property - def name(self): - return self.__name - - @name.setter - def name(self, name): - self.__name = name - if not self.__name: - self.__opt_is_tmpl_inst = None - self.__opt_tmpl_name = None - self.__opt_is_full_name = None - self.__decl_name_only = None - else: - self.__opt_is_tmpl_inst = templates.is_instantiation(self.__name) - self.__opt_tmpl_name = templates.name(self.__name) - if self.__opt_is_tmpl_inst: - if '::' in self.__opt_tmpl_name: - self.__opt_is_full_name = True - self.__decl_name_only = \ - self.__opt_tmpl_name.split('::')[-1] - else: - self.__opt_is_full_name = False - self.__decl_name_only = self.__opt_tmpl_name - self.__name = templates.normalize(name) - else: - if '::' in self.__name: - self.__opt_is_full_name = True - self.__decl_name_only = self.__name.split('::')[-1] - else: - self.__opt_is_full_name = False - self.__decl_name_only = self.__name - - def __str__(self): - msg = [] - if self.decl_type is not None: - msg.append('(decl type==%s)' % self.decl_type.__name__) - if self.name is not None: - msg.append('(name==%s)' % self.name) - if self.header_dir is not None: - msg.append('(header dir==%s)' % self.header_dir) - if self.header_file is not None: - msg.append('(header file==%s)' % self.header_file) - if not msg: - msg.append('any') - return ' and '.join(msg) - - def __call__(self, decl): - if self.decl_type is not None: - if not isinstance(decl, self.decl_type): - return False - if self.name is not None: - if not self.check_name(decl): - return False - if self.header_dir is not None: - if decl.location: - decl_dir = os.path.abspath( - os.path.dirname(decl.location.file_name)) - decl_dir = utils.normalize_path(decl_dir) - if decl_dir[:len(self.header_dir)] != self.header_dir: - return False - else: - return False - if self.header_file is not None: - if decl.location: - decl_file = os.path.abspath(decl.location.file_name) - decl_file = utils.normalize_path(decl_file) - if decl_file != self.header_file: - return False - else: - return False - return True - - def check_name(self, decl): - assert self.name is not None - if self.__opt_is_tmpl_inst: - if not self.__opt_is_full_name: - if self.name != templates.normalize(decl.name) \ - and self.name != templates.normalize(decl.partial_name): - return False - else: - if self.name != templates.normalize( - declaration_utils.full_name( - decl, with_defaults=True)) \ - and self.name != templates.normalize( - declaration_utils.full_name( - decl, with_defaults=False)): - return False - else: - if not self.__opt_is_full_name: - if self.name != decl.name and self.name != decl.partial_name: - return False - else: - if self.name != declaration_utils.full_name( - decl, with_defaults=True) \ - and self.name != declaration_utils.full_name( - decl, with_defaults=False): - return False - return True - - def is_full_name(self): - return self.__opt_is_full_name - - @property - def decl_name_only(self): - return self.__decl_name_only - - -class variable_matcher_t(declaration_matcher_t): - - """ - Instance of this class will match variables by next criteria: - - :class:`declaration_matcher_t` criteria - - variable type. Example: :class:`int_t` or 'int' - """ - - def __init__( - self, - name=None, - type=None, - decl_type=None, - header_dir=None, - header_file=None): - """ - :param decl_type: variable type - :type decl_type: string or instance of :class:`type_t` derived class - """ - - if type is not None: - # Deprecated since 1.8.0. Will be removed in 1.9.0 - warnings.warn( - "The type argument is deprecated. \n" + - "Please use the decl_type argument instead.", - DeprecationWarning) - if decl_type is not None: - raise ( - "Please use only either the type or " + - "decl_type argument.") - # Still allow to use the old type for the moment. - decl_type = type - - declaration_matcher_t.__init__( - self, - name=name, - decl_type=variable.variable_t, - header_dir=header_dir, - header_file=header_file) - self._decl_type = decl_type - - def __call__(self, decl): - if not super(variable_matcher_t, self).__call__(decl): - return False - if self._decl_type is not None: - if isinstance(self._decl_type, cpptypes.type_t): - if self._decl_type != decl.decl_type: - return False - else: - if self._decl_type != decl.decl_type.decl_string: - return False - return True - - def __str__(self): - msg = [super(variable_matcher_t, self).__str__()] - if msg == ['any']: - msg = [] - if self._decl_type is not None: - msg.append('(value type==%s)' % str(self._decl_type)) - if not msg: - msg.append('any') - return ' and '.join(msg) - - -class namespace_matcher_t(declaration_matcher_t): - - """Instance of this class will match namespaces by name.""" - - def __init__(self, name=None): - declaration_matcher_t.__init__( - self, - name=name, - decl_type=namespace.namespace_t) - - def __call__(self, decl): - if self.name and decl.name == '': - # unnamed namespace have same name as thier parent, we should - # prevent this happens. The price is: user should search for - # unnamed namespace directly. - return False - return super(namespace_matcher_t, self).__call__(decl) - - -class calldef_matcher_t(declaration_matcher_t): - - """ - Instance of this class will match callable by the following criteria: - * :class:`declaration_matcher_t` criteria - * return type. For example: :class:`int_t` or 'int' - * argument types - - """ - - def __init__( - self, - name=None, - return_type=None, - arg_types=None, - decl_type=None, - header_dir=None, - header_file=None): - """ - :param return_type: callable return type - :type return_type: string or instance of :class:`type_t` derived class - - :type arg_types: list - :param arg_types: list of function argument types. `arg_types` can - contain. - Any item within the list could be string or instance - of :class:`type_t` derived class. If you don't want - some argument to participate in match you can put - None. - - For example: - - .. code-block:: python - - calldef_matcher_t( arg_types=[ 'int &', None ] ) - - will match all functions that takes 2 arguments, where the first one is - reference to integer and second any - """ - if None is decl_type: - decl_type = calldef.calldef_t - declaration_matcher_t.__init__( - self, - name=name, - decl_type=decl_type, - header_dir=header_dir, - header_file=header_file) - - self.return_type = return_type - self.arg_types = arg_types - - def __call__(self, decl): - if not super(calldef_matcher_t, self).__call__(decl): - return False - if self.return_type is not None \ - and not self.__compare_types(self.return_type, decl.return_type): - return False - if self.arg_types: - if isinstance(self.arg_types, (list, tuple)): - if len(self.arg_types) != len(decl.arguments): - return False - for type_or_str, arg in zip(self.arg_types, decl.arguments): - if type_or_str is None: - continue - else: - if not self.__compare_types( - type_or_str, arg.decl_type): - return False - return True - - def __compare_types(self, type_or_str, type): - assert type_or_str - if type is None: - return False - if isinstance(type_or_str, cpptypes.type_t): - if type_or_str != type: - return False - else: - if type_or_str != type.decl_string: - return False - return True - - def __str__(self): - msg = [super(calldef_matcher_t, self).__str__()] - if msg == ['any']: - msg = [] - if self.return_type is not None: - msg.append('(return type==%s)' % str(self.return_type)) - if self.arg_types: - for i, arg_type in enumerate(self.arg_types): - if arg_type is None: - msg.append('(arg %d type==any)' % i) - else: - msg.append('(arg %d type==%s)' % (i, str(arg_type))) - if not msg: - msg.append('any') - return ' and '.join(msg) - - -class operator_matcher_t(calldef_matcher_t): - - """ - Instance of this class will match operators by next criteria: - * :class:`calldef_matcher_t` criteria - * operator symbol: =, !=, (), [] and etc - """ - - def __init__( - self, - name=None, - symbol=None, - return_type=None, - arg_types=None, - decl_type=None, - header_dir=None, - header_file=None): - """ - :param symbol: operator symbol - :type symbol: str - """ - if None is decl_type: - decl_type = calldef_members.operator_t - calldef_matcher_t.__init__( - self, - name=name, - return_type=return_type, - arg_types=arg_types, - decl_type=decl_type, - header_dir=header_dir, - header_file=header_file) - self.symbol = symbol - - def __call__(self, decl): - if not super(operator_matcher_t, self).__call__(decl): - return False - if self.symbol is not None: - if self.symbol != decl.symbol: - return False - return True - - def __str__(self): - msg = [super(operator_matcher_t, self).__str__()] - if msg == ['any']: - msg = [] - if self.symbol is not None: - msg.append('(symbol==%s)' % str(self.symbol)) - if not msg: - msg.append('any') - return ' and '.join(msg) - - class regex_matcher_t(matcher_base_t): """ @@ -567,6 +153,27 @@ def __str__(self): return '(regex=%s)' % self.regex +class custom_matcher_t(matcher_base_t): + + """ + Instance of this class will match declaration by user custom criteria. + """ + + def __init__(self, function): + """ + :param function: callable, that takes single argument - + declaration instance should return True or False + """ + matcher_base_t.__init__(self) + self.function = function + + def __call__(self, decl): + return bool(self.function(decl)) + + def __str__(self): + return '(user criteria)' + + class access_type_matcher_t(matcher_base_t): """ @@ -619,24 +226,3 @@ def __call__(self, decl): def __str__(self): return '(virtuality type=%s)' % self.virtuality_type - - -class custom_matcher_t(matcher_base_t): - - """ - Instance of this class will match declaration by user custom criteria. - """ - - def __init__(self, function): - """ - :param function: callable, that takes single argument - - declaration instance should return True or False - """ - matcher_base_t.__init__(self) - self.function = function - - def __call__(self, decl): - return bool(self.function(decl)) - - def __str__(self): - return '(user criteria)' From 92ae782bbf226af686681a24d701c06bce375731 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 6 Jun 2016 22:10:14 +0200 Subject: [PATCH 173/268] Move some has_xxx_operator methods to a separate module This removes the matchers module dependency from the type_traits module --- pygccxml/declarations/__init__.py | 7 ++- pygccxml/declarations/has_operator_matcher.py | 60 +++++++++++++++++++ pygccxml/declarations/type_traits.py | 56 ----------------- 3 files changed, 64 insertions(+), 59 deletions(-) create mode 100644 pygccxml/declarations/has_operator_matcher.py diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 4af550a8..f2115cef 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -166,10 +166,8 @@ from .type_traits import remove_declarated from .type_traits import has_destructor -from .type_traits import has_public_less from .type_traits import has_copy_constructor -from .type_traits import has_public_equal from .type_traits import has_public_assign from .type_traits import has_public_destructor from .type_traits import has_public_constructor @@ -177,9 +175,12 @@ from .type_traits import find_trivial_constructor from .type_traits import find_copy_constructor from .type_traits import find_noncopyable_vars -from .type_traits import has_public_binary_operator from .type_traits import has_any_non_copyconstructor +from .has_operator_matcher import has_public_binary_operator +from .has_operator_matcher import has_public_equal +from .has_operator_matcher import has_public_less + from .type_traits import auto_ptr_traits from .type_traits import smart_pointer_traits from .type_traits import internal_type_traits diff --git a/pygccxml/declarations/has_operator_matcher.py b/pygccxml/declarations/has_operator_matcher.py new file mode 100644 index 00000000..0c054015 --- /dev/null +++ b/pygccxml/declarations/has_operator_matcher.py @@ -0,0 +1,60 @@ +from . import type_traits +from . import type_traits_utils +from . import class_declaration +from . import matchers +from . import cpptypes + + +def has_public_binary_operator(type_, operator_symbol): + """returns True, if `type_` has public binary operator, otherwise False""" + type_ = type_traits_utils.remove_alias(type_) + type_ = type_traits.remove_cv(type_) + type_ = type_traits.remove_declarated(type_) + assert isinstance(type_, class_declaration.class_t) + + if type_traits.is_std_string(type_) or type_traits.is_std_wstring(type_): + # In some case compare operators of std::basic_string are not + # instantiated + return True + + operators = type_.member_operators( + function=matchers.custom_matcher_t( + lambda decl: not decl.is_artificial) & + matchers.access_type_matcher_t('public'), + symbol=operator_symbol, allow_empty=True, recursive=False) + if operators: + return True + + t = cpptypes.declarated_t(type_) + t = cpptypes.const_t(t) + t = cpptypes.reference_t(t) + operators = type_.top_parent.operators( + function=lambda decl: not decl.is_artificial, + arg_types=[t, None], + symbol=operator_symbol, + allow_empty=True, + recursive=True) + if operators: + return True + for bi in type_.recursive_bases: + assert isinstance(bi, class_declaration.hierarchy_info_t) + if bi.access_type != class_declaration.ACCESS_TYPES.PUBLIC: + continue + operators = bi.related_class.member_operators( + function=matchers.custom_matcher_t( + lambda decl: not decl.is_artificial) & + matchers.access_type_matcher_t('public'), + symbol=operator_symbol, allow_empty=True, recursive=False) + if operators: + return True + return False + + +def has_public_equal(type): + """returns True, if class has public operator==, otherwise False""" + return has_public_binary_operator(type, '==') + + +def has_public_less(type): + """returns True, if class has public operator<, otherwise False""" + return has_public_binary_operator(type, '<') diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index b31079f9..337ed8d3 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -20,7 +20,6 @@ import os -from . import matchers from . import calldef from . import calldef_members from . import calldef_types @@ -616,61 +615,6 @@ def has_any_non_copyconstructor(type): return decls -def has_public_binary_operator(type_, operator_symbol): - """returns True, if `type_` has public binary operator, otherwise False""" - type_ = type_traits_utils.remove_alias(type_) - type_ = remove_cv(type_) - type_ = remove_declarated(type_) - assert isinstance(type_, class_declaration.class_t) - - if is_std_string(type_) or is_std_wstring(type_): - # In some case compare operators of std::basic_string are not - # instantiated - return True - - operators = type_.member_operators( - function=matchers.custom_matcher_t( - lambda decl: not decl.is_artificial) & - matchers.access_type_matcher_t('public'), - symbol=operator_symbol, allow_empty=True, recursive=False) - if operators: - return True - - t = cpptypes.declarated_t(type_) - t = cpptypes.const_t(t) - t = cpptypes.reference_t(t) - operators = type_.top_parent.operators( - function=lambda decl: not decl.is_artificial, - arg_types=[t, None], - symbol=operator_symbol, - allow_empty=True, - recursive=True) - if operators: - return True - for bi in type_.recursive_bases: - assert isinstance(bi, class_declaration.hierarchy_info_t) - if bi.access_type != class_declaration.ACCESS_TYPES.PUBLIC: - continue - operators = bi.related_class.member_operators( - function=matchers.custom_matcher_t( - lambda decl: not decl.is_artificial) & - matchers.access_type_matcher_t('public'), - symbol=operator_symbol, allow_empty=True, recursive=False) - if operators: - return True - return False - - -def has_public_equal(type): - """returns True, if class has public operator==, otherwise False""" - return has_public_binary_operator(type, '==') - - -def has_public_less(type): - """returns True, if class has public operator<, otherwise False""" - return has_public_binary_operator(type, '<') - - def is_unary_operator(oper): """returns True, if operator is unary operator, otherwise False""" # definition: From 1d09dcf449555c6539d1214ee29a3783daca910e Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 7 Jun 2016 21:51:48 +0200 Subject: [PATCH 174/268] Split the type_traits module in two One part, which remained in the type_traits module, are the basic functions needed to work with type_traits. These functions need very few dependenies. The second part are all the functions which are related to classes. This allows now to import the type_traits module mostly everywhere without cyclic import problems. The type_traits_classes is then the more specialized version from the type_traits module. The split makes also sense as the type_traits module was very long, and the logical split is welcome. --- pygccxml/declarations/__init__.py | 76 +- pygccxml/declarations/calldef_members.py | 8 +- pygccxml/declarations/class_declaration.py | 16 +- pygccxml/declarations/container_traits.py | 173 +++- pygccxml/declarations/decl_printer.py | 5 +- pygccxml/declarations/free_calldef.py | 10 +- pygccxml/declarations/function_traits.py | 15 +- pygccxml/declarations/type_traits.py | 967 ------------------- pygccxml/declarations/type_traits_classes.py | 837 ++++++++++++++++ unittests/unnamed_classes_tester.py | 8 +- 10 files changed, 1079 insertions(+), 1036 deletions(-) create mode 100644 pygccxml/declarations/type_traits_classes.py diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index f2115cef..182415c8 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -117,17 +117,6 @@ from .decl_visitor import decl_visitor_t from .type_visitor import type_visitor_t - -from .type_traits import is_enum -from .type_traits import enum_declaration -from .type_traits import enum_traits - -from .type_traits import is_class -from .type_traits import class_traits -from .type_traits import is_class_declaration -from .type_traits import class_declaration_traits - - from .type_traits import is_bool from .type_traits import is_same from .type_traits import is_void @@ -141,19 +130,11 @@ from .type_traits import is_arithmetic from .type_traits import is_fundamental from .type_traits import is_floating_point -from .type_traits import is_base_and_derived -from .type_traits import is_convertible -from .type_traits import is_noncopyable from .type_traits import is_std_string from .type_traits import is_std_wstring from .type_traits import is_std_ostream from .type_traits import is_std_wostream from .type_traits import is_calldef_pointer -from .type_traits import is_copy_constructor -from .type_traits import is_trivial_constructor - -from .type_traits import is_unary_operator -from .type_traits import is_binary_operator from .type_traits import array_size from .type_traits import array_item_type @@ -165,30 +146,42 @@ from .type_traits import remove_reference from .type_traits import remove_declarated -from .type_traits import has_destructor -from .type_traits import has_copy_constructor - -from .type_traits import has_public_assign -from .type_traits import has_public_destructor -from .type_traits import has_public_constructor -from .type_traits import has_trivial_constructor -from .type_traits import find_trivial_constructor -from .type_traits import find_copy_constructor -from .type_traits import find_noncopyable_vars -from .type_traits import has_any_non_copyconstructor - from .has_operator_matcher import has_public_binary_operator from .has_operator_matcher import has_public_equal from .has_operator_matcher import has_public_less -from .type_traits import auto_ptr_traits -from .type_traits import smart_pointer_traits -from .type_traits import internal_type_traits - -from .type_traits_utils import decompose_type -from .type_traits_utils import decompose_class -from .type_traits_utils import base_type -from .type_traits_utils import remove_alias +from .type_traits_classes import is_enum +from .type_traits_classes import enum_declaration +from .type_traits_classes import enum_traits +from .type_traits_classes import is_class +from .type_traits_classes import class_traits +from .type_traits_classes import is_class_declaration +from .type_traits_classes import class_declaration_traits +from .type_traits_classes import is_base_and_derived +from .type_traits_classes import is_convertible +from .type_traits_classes import is_noncopyable +from .type_traits_classes import is_copy_constructor +from .type_traits_classes import is_trivial_constructor +from .type_traits_classes import is_union + +from .type_traits_classes import is_unary_operator +from .type_traits_classes import is_binary_operator + +from .type_traits_classes import has_destructor +from .type_traits_classes import has_copy_constructor + +from .type_traits_classes import has_public_assign +from .type_traits_classes import has_public_destructor +from .type_traits_classes import has_public_constructor +from .type_traits_classes import has_trivial_constructor +from .type_traits_classes import find_trivial_constructor +from .type_traits_classes import find_copy_constructor +from .type_traits_classes import find_noncopyable_vars +from .type_traits_classes import has_any_non_copyconstructor + +from .container_traits import auto_ptr_traits +from .container_traits import smart_pointer_traits +from .container_traits import internal_type_traits from .container_traits import list_traits from .container_traits import deque_traits @@ -213,6 +206,11 @@ from .function_traits import is_same_function +from .type_traits_utils import decompose_type +from .type_traits_utils import decompose_class +from .type_traits_utils import base_type +from .type_traits_utils import remove_alias + from . import templates from . import call_invocation diff --git a/pygccxml/declarations/calldef_members.py b/pygccxml/declarations/calldef_members.py index 94a22acb..3c76e62b 100644 --- a/pygccxml/declarations/calldef_members.py +++ b/pygccxml/declarations/calldef_members.py @@ -202,8 +202,8 @@ def is_copy_constructor(self): DeprecationWarning) # prevent cyclic dependencies - from . import type_traits - return type_traits.is_copy_constructor(self) + from . import type_traits_classes + return type_traits_classes.is_copy_constructor(self) @property def is_trivial_constructor(self): @@ -216,8 +216,8 @@ def is_trivial_constructor(self): DeprecationWarning) # prevent cyclic dependencies - from . import type_traits - return type_traits.is_trivial_constructor(self) + from . import type_traits_classes + return type_traits_classes.is_trivial_constructor(self) class destructor_t(member_calldef_t): diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 4bc50e21..cab28fc5 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -560,8 +560,8 @@ def find_copy_constructor(self): "declarations module instead.", DeprecationWarning) - from . import type_traits # prevent cyclic dependencies - return type_traits.find_copy_constructor(self) + from . import type_traits_classes # prevent cyclic dependencies + return type_traits_classes.find_copy_constructor(self) def find_trivial_constructor(self): @@ -572,8 +572,8 @@ def find_trivial_constructor(self): "declarations module instead.", DeprecationWarning) - from . import type_traits # prevent cyclic dependencies - return type_traits.find_trivial_constructor(self) + from . import type_traits_classes # prevent cyclic dependencies + return type_traits_classes.find_trivial_constructor(self) def _get_partial_name_impl(self): from . import type_traits # prevent cyclic dependencies @@ -594,8 +594,8 @@ def find_noncopyable_vars(self): "declarations module instead.", DeprecationWarning) - from . import type_traits # prevent cyclic dependencies - type_traits.find_noncopyable_vars(self) + from . import type_traits_classes # prevent cyclic dependencies + type_traits_classes.find_noncopyable_vars(self) @property def has_vtable(self): @@ -609,8 +609,8 @@ def has_vtable(self): DeprecationWarning) # prevent cyclic import - from . import type_traits - return type_traits.has_vtable(self) + from . import type_traits_classes + return type_traits_classes.has_vtable(self) @property def top_class(self): diff --git a/pygccxml/declarations/container_traits.py b/pygccxml/declarations/container_traits.py index 2c8e8255..cfa93594 100644 --- a/pygccxml/declarations/container_traits.py +++ b/pygccxml/declarations/container_traits.py @@ -15,6 +15,8 @@ from . import type_traits_utils from . import namespace from . import class_declaration +from . import calldef +from . import class_declaration_traits from .. import utils std_namespaces = ('std', 'stdext', '__gnu_cxx') @@ -421,7 +423,7 @@ def get_container_or_none(self, type_): decl = cls_declaration.parent for ns in std_namespaces: - if type_traits.impl_details.is_defined_in_xxx(ns, decl): + if impl_details.is_defined_in_xxx(ns, decl): utils.loggers.queries_engine.debug( "Container traits: get_container_or_none() will return " + cls_declaration.name) @@ -481,7 +483,7 @@ def __find_xxx_type( result = type_traits.remove_declarated(xxx_type) else: xxx_type_str = templates.args(cls_declaration.name)[xxx_index] - result = type_traits.impl_details.find_value_type( + result = impl_details.find_value_type( cls_declaration.top_parent, xxx_type_str) if None is result: raise RuntimeError( @@ -702,3 +704,170 @@ def find_container_traits(cls_or_string): for cls_traits in container_traits: if cls_traits.is_my_case(cls_or_string): return cls_traits + + +class impl_details(object): + + """implementation details""" + @staticmethod + def is_defined_in_xxx(xxx, cls): + """implementation details""" + if not cls.parent: + return False + + if not isinstance(cls.parent, namespace.namespace_t): + return False + + if xxx != cls.parent.name: + return False + + xxx_ns = cls.parent + if not xxx_ns.parent: + return False + + if not isinstance(xxx_ns.parent, namespace.namespace_t): + return False + + if '::' != xxx_ns.parent.name: + return False + + global_ns = xxx_ns.parent + return None is global_ns.parent + + @staticmethod + def find_value_type(global_ns, value_type_str): + """implementation details""" + if not value_type_str.startswith('::'): + value_type_str = '::' + value_type_str + found = global_ns.decls( + name=value_type_str, + function=lambda decl: not isinstance(decl, calldef.calldef_t), + allow_empty=True) + if not found: + no_global_ns_value_type_str = value_type_str[2:] + if no_global_ns_value_type_str in cpptypes.FUNDAMENTAL_TYPES: + return cpptypes.FUNDAMENTAL_TYPES[no_global_ns_value_type_str] + elif type_traits.is_std_string(value_type_str): + string_ = global_ns.typedef('::std::string') + return type_traits.remove_declarated(string_) + elif type_traits.is_std_wstring(value_type_str): + string_ = global_ns.typedef('::std::wstring') + return type_traits.remove_declarated(string_) + else: + value_type_str = no_global_ns_value_type_str + has_const = value_type_str.startswith('const ') + if has_const: + value_type_str = value_type_str[len('const '):] + has_pointer = value_type_str.endswith('*') + if has_pointer: + value_type_str = value_type_str[:-1] + found = None + if has_const or has_pointer: + found = impl_details.find_value_type( + global_ns, + value_type_str) + if not found: + return None + else: + if isinstance(found, class_declaration.class_types): + found = cpptypes.declarated_t(found) + if has_const: + found = cpptypes.const_t(found) + if has_pointer: + found = cpptypes.pointer_t(found) + return found + if len(found) == 1: + return found[0] + else: + return None + + +class internal_type_traits(object): + + """small convenience class, which provides access to internal types""" + # TODO: add exists function + @staticmethod + def get_by_name(type_, name): + if class_declaration_traits.class_traits.is_my_case(type_): + cls = class_declaration_traits.class_traits.declaration_class( + type_) + return type_traits.remove_declarated( + cls.typedef(name, recursive=False).decl_type) + elif class_declaration_traits.is_my_case(type_): + cls = class_declaration_traits.get_declaration(type_) + value_type_str = templates.args(cls.name)[0] + ref = impl_details.find_value_type(cls.top_parent, value_type_str) + if ref: + return ref + else: + raise RuntimeError(( + "Unable to find reference to internal " + + "type '%s' in type '%s'.") % (name, cls.decl_string)) + else: + raise RuntimeError(( + "Unable to find reference to internal type '%s' in type '%s'.") + % (name, type_.decl_string)) + + +class smart_pointer_traits(object): + + """implements functionality, needed for convenient work with + smart pointers""" + + @staticmethod + def is_smart_pointer(type_): + """returns True, if type represents instantiation of + `boost::shared_ptr` or `std::shared_ptr`, False otherwise""" + type_ = type_traits_utils.remove_alias(type_) + type_ = type_traits.remove_cv(type_) + type_ = type_traits.remove_declarated(type_) + if not isinstance(type_, + (class_declaration.class_declaration_t, + class_declaration.class_t)): + return False + if not (impl_details.is_defined_in_xxx('boost', type_) or + impl_details.is_defined_in_xxx('std', type_)): + return False + return type_.decl_string.startswith('::boost::shared_ptr<') or \ + type_.decl_string.startswith('::std::shared_ptr<') + + @staticmethod + def value_type(type_): + """returns reference to `boost::shared_ptr` \ + or `std::shared_ptr` value type""" + if not smart_pointer_traits.is_smart_pointer(type_): + raise TypeError( + 'Type "%s" is not an instantiation of \ + boost::shared_ptr or std::shared_ptr' % + type_.decl_string) + return internal_type_traits.get_by_name(type_, "value_type") + + +class auto_ptr_traits(object): + + """implements functionality, needed for convenient work with + `std::auto_ptr` pointers""" + + @staticmethod + def is_smart_pointer(type_): + """returns True, if type represents instantiation of + `boost::shared_ptr`, False otherwise""" + type_ = type_traits_utils.remove_alias(type_) + type_ = type_traits.remove_cv(type_) + type_ = type_traits.remove_declarated(type_) + if not isinstance(type_, + (class_declaration.class_declaration_t, + class_declaration.class_t)): + return False + if not impl_details.is_defined_in_xxx('std', type_): + return False + return type_.decl_string.startswith('::std::auto_ptr<') + + @staticmethod + def value_type(type_): + """returns reference to `boost::shared_ptr` value type""" + if not auto_ptr_traits.is_smart_pointer(type_): + raise TypeError( + 'Type "%s" is not instantiation of std::auto_ptr' % + type_.decl_string) + return internal_type_traits.get_by_name(type_, "element_type") diff --git a/pygccxml/declarations/decl_printer.py b/pygccxml/declarations/decl_printer.py index 26bf0600..bdd2302f 100644 --- a/pygccxml/declarations/decl_printer.py +++ b/pygccxml/declarations/decl_printer.py @@ -15,7 +15,7 @@ from . import decl_visitor from . import variable_t from . import calldef_t -from . import type_traits +from . import type_traits_classes from .. import utils @@ -244,7 +244,8 @@ def visit_constructor(self): if self.__print_details: self.writer(indent + 'copy constructor: ' + - str(type_traits.is_copy_constructor(self.__inst)) + + str(type_traits_classes.is_copy_constructor( + self.__inst)) + os.linesep) def visit_destructor(self): diff --git a/pygccxml/declarations/free_calldef.py b/pygccxml/declarations/free_calldef.py index 73bc015d..0363c63f 100644 --- a/pygccxml/declarations/free_calldef.py +++ b/pygccxml/declarations/free_calldef.py @@ -9,6 +9,7 @@ from . import declaration_utils from . import cpptypes from . import type_traits +from . import type_traits_classes class free_calldef_t(calldef.calldef_t): @@ -100,10 +101,11 @@ def class_types(self): for type_ in self.argument_types: decl = None type_ = type_traits.remove_reference(type_) - if type_traits.is_class(type_): - decl = type_traits.class_traits.get_declaration(type_) - elif type_traits.is_class_declaration(type_): - tt = type_traits.class_declaration_traits + if type_traits_classes.is_class(type_): + decl = type_traits_classes.class_traits.get_declaration( + type_) + elif type_traits_classes.is_class_declaration(type_): + tt = type_traits_classes.class_declaration_traits decl = tt.get_declaration(type_) else: pass diff --git a/pygccxml/declarations/function_traits.py b/pygccxml/declarations/function_traits.py index 6e462a1a..37faa6bc 100644 --- a/pygccxml/declarations/function_traits.py +++ b/pygccxml/declarations/function_traits.py @@ -10,6 +10,7 @@ from . import calldef_types from . import calldef_members from . import type_traits +from . import type_traits_classes def is_same_return_type(f1, f2): @@ -54,17 +55,19 @@ def is_same_return_type(f1, f2): rt2 = type_traits.remove_const(rt2) else: return False - if not type_traits.is_class(rt1) or not type_traits.is_class(rt2): + if not type_traits_classes.is_class(rt1) or not \ + type_traits_classes.is_class(rt2): return type_traits.is_same(rt1, rt2) - if type_traits.is_union(rt1) or type_traits.is_union(rt2): + if type_traits_classes.is_union(rt1) or \ + type_traits_classes.is_union(rt2): return type_traits.is_same(rt1, rt2) - c1 = type_traits.class_traits.get_declaration(rt1) - c2 = type_traits.class_traits.get_declaration(rt2) + c1 = type_traits_classes.class_traits.get_declaration(rt1) + c2 = type_traits_classes.class_traits.get_declaration(rt2) return type_traits.is_same(c1, c2) \ - or type_traits.is_base_and_derived(c1, c2) \ - or type_traits.is_base_and_derived(c2, c1) + or type_traits_classes.is_base_and_derived(c1, c2) \ + or type_traits_classes.is_base_and_derived(c2, c1) def is_same_function(f1, f2): diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 337ed8d3..be30f075 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -18,17 +18,8 @@ """ -import os - -from . import calldef -from . import calldef_members -from . import calldef_types from . import cpptypes from . import namespace -from . import scopedef -from . import templates -from . import enumeration -from . import class_declaration from . import type_traits_utils from .. import utils @@ -351,727 +342,6 @@ def is_fundamental(type): (cpptypes.volatile_t, cpptypes.const_t)) -def is_union(type_): - """returns True if type represents a C++ union""" - if not is_class(type_): - return False - decl = class_traits.get_declaration(type_) - return decl.class_type == class_declaration.CLASS_TYPES.UNION - - -class declaration_xxx_traits(object): - """this class implements the functionality needed for convenient work with - declaration classes - - Implemented functionality: - - find out whether a declaration is a desired one - - get reference to the declaration - """ - sequence = [type_traits_utils.remove_alias, remove_cv, remove_declarated] - - def __init__(self, declaration_class): - self.declaration_class = declaration_class - - def __apply_sequence(self, type_): - for f in self.sequence: - type_ = f(type_) - return type_ - - def is_my_case(self, type_): - """returns True, if type represents the desired declaration, - False otherwise""" - return ( - isinstance(self.__apply_sequence(type_), self.declaration_class) - ) - - def get_declaration(self, type_): - """returns reference to the declaration - - Precondition: self.is_my_case( type ) == True - """ - return self.__apply_sequence(type_) - -enum_traits = declaration_xxx_traits(enumeration.enumeration_t) -"""implements functionality, needed for convenient work with C++ enums""" - -is_enum = enum_traits.is_my_case -"""returns True, if type represents C++ enumeration declaration, -False otherwise""" - -enum_declaration = enum_traits.get_declaration -"""returns reference to enum declaration""" - -class_traits = declaration_xxx_traits(class_declaration.class_t) -"""implements functionality, needed for convenient work with C++ classes""" - -is_class = class_traits.is_my_case -"""returns True, if type represents C++ class definition, False otherwise""" - -class_declaration_traits = declaration_xxx_traits( - class_declaration.class_declaration_t) -"""implements functionality, needed for convenient work with C++ class -declarations""" - -is_class_declaration = class_declaration_traits.is_my_case -"""returns True, if type represents C++ class declaration, False otherwise""" - - -def find_trivial_constructor(type_): - """ - Returns reference to trivial constructor. - - Args: - type_ (declarations.class_t): the class to be searched. - - Returns: - declarations.constructor_t: the trivial constructor - - """ - assert isinstance(type_, class_declaration.class_t) - - trivial = type_.constructors( - lambda x: is_trivial_constructor(x), - recursive=False, - allow_empty=True) - if trivial: - return trivial[0] - else: - return None - - -def find_copy_constructor(type_): - """ - Returns reference to copy constructor. - - Args: - type_ (declarations.class_t): the class to be searched. - - Returns: - declarations.constructor_t: the copy constructor - - """ - copy_ = type_.constructors( - lambda x: is_copy_constructor(x), - recursive=False, - allow_empty=True) - if copy_: - return copy_[0] - else: - return None - - -def find_noncopyable_vars(type_): - """ - Returns list of all `noncopyable` variables. - - Args: - type_ (declarations.class_t): the class to be searched. - - Returns: - list: list of all `noncopyable` variables. - - """ - assert(isinstance(type_, class_declaration.class_t)) - - logger = utils.loggers.cxx_parser - mvars = type_.variables( - lambda v: not v.type_qualifiers.has_static, - recursive=False, - allow_empty=True) - noncopyable_vars = [] - - message = ( - "__contains_noncopyable_mem_var - %s - TRUE - " + - "contains const member variable") - - for mvar in mvars: - - type_ = remove_reference(mvar.decl_type) - - if is_const(type_): - no_const = remove_const(type_) - if is_fundamental(no_const) or is_enum(no_const): - logger.debug((message + "- fundamental or enum") - % type_.decl_string) - noncopyable_vars.append(mvar) - if is_class(no_const): - logger.debug((message + " - class") % type_.decl_string) - noncopyable_vars.append(mvar) - if is_array(no_const): - logger.debug((message + " - array") % type_.decl_string) - noncopyable_vars.append(mvar) - - if class_traits.is_my_case(type_): - - cls = class_traits.get_declaration(type_) - if is_noncopyable(cls): - logger.debug((message + " - class that is not copyable") - % type_.decl_string) - noncopyable_vars.append(mvar) - - logger.debug( - ("__contains_noncopyable_mem_var - %s - FALSE - doesn't " + - "contain noncopyable members") % type_.decl_string) - - return noncopyable_vars - - -def has_trivial_constructor(class_): - """if class has public trivial constructor, this function will return - reference to it, None otherwise""" - class_ = class_traits.get_declaration(class_) - trivial = find_trivial_constructor(class_) - if trivial and trivial.access_type == 'public': - return trivial - - -def has_copy_constructor(class_): - """if class has public copy constructor, this function will return - reference to it, None otherwise""" - class_ = class_traits.get_declaration(class_) - copy_constructor = find_copy_constructor(class_) - if copy_constructor and copy_constructor.access_type == 'public': - return copy_constructor - - -def has_destructor(class_): - """if class has destructor, this function will return reference to it, - None otherwise""" - class_ = class_traits.get_declaration(class_) - destructor = class_.decls( - decl_type=calldef_members.destructor_t, - recursive=False, - allow_empty=True) - if destructor: - return destructor[0] - - -def has_public_constructor(class_): - """if class has any public constructor, this function will return list of - them, otherwise None""" - class_ = class_traits.get_declaration(class_) - decls = class_.constructors( - lambda c: not is_copy_constructor(c) and c.access_type == 'public', - recursive=False, - allow_empty=True) - if decls: - return decls - - -def has_public_assign(class_): - """returns True, if class has public assign operator, False otherwise""" - class_ = class_traits.get_declaration(class_) - decls = class_.mem_opers( - lambda o: o.symbol == '=' and o.access_type == 'public', - recursive=False, - allow_empty=True) - return bool(decls) - - -def has_public_destructor(type): - """returns True, if class has public destructor, False otherwise""" - d = has_destructor(type) - return d and d.access_type == 'public' - - -def has_vtable(type_): - """True, if class has virtual table, False otherwise""" - assert(isinstance(type_, class_declaration.class_t)) - return bool( - type_.calldefs( - lambda f: isinstance(f, calldef_members.member_function_t) and - f.virtuality != calldef_types.VIRTUALITY_TYPES.NOT_VIRTUAL, - recursive=False, - allow_empty=True)) - - -def is_base_and_derived(based, derived): - """returns True, if there is "base and derived" relationship between - classes, False otherwise""" - assert isinstance(based, class_declaration.class_t) - assert isinstance(derived, (class_declaration.class_t, tuple)) - - if isinstance(derived, class_declaration.class_t): - all_derived = ([derived]) - else: # tuple - all_derived = derived - - for derived_cls in all_derived: - for base_desc in derived_cls.recursive_bases: - if base_desc.related_class == based: - return True - return False - - -def has_any_non_copyconstructor(type): - """if class has any public constructor, which is not copy constructor, - this function will return list of them, otherwise None""" - class_ = class_traits.get_declaration(type) - decls = class_.constructors( - lambda c: not is_copy_constructor(c) and c.access_type == 'public', - recursive=False, - allow_empty=True) - if decls: - return decls - - -def is_unary_operator(oper): - """returns True, if operator is unary operator, otherwise False""" - # definition: - # memeber in class - # ret-type operator symbol() - # ret-type operator [++ --](int) - # globally - # ret-type operator symbol( arg ) - # ret-type operator [++ --](X&, int) - symbols = ['!', '&', '~', '*', '+', '++', '-', '--'] - if not isinstance(oper, calldef_members.operator_t): - return False - if oper.symbol not in symbols: - return False - if isinstance(oper, calldef_members.member_operator_t): - if 0 == len(oper.arguments): - return True - elif oper.symbol in ['++', '--'] and \ - isinstance(oper.arguments[0].decl_type, cpptypes.int_t): - return True - else: - return False - else: - if 1 == len(oper.arguments): - return True - elif oper.symbol in ['++', '--'] \ - and 2 == len(oper.arguments) \ - and isinstance(oper.arguments[1].decl_type, cpptypes.int_t): - # may be I need to add additional check whether first argument is - # reference or not? - return True - else: - return False - - -def is_binary_operator(oper): - """returns True, if operator is binary operator, otherwise False""" - # definition: - # memeber in class - # ret-type operator symbol(arg) - # globally - # ret-type operator symbol( arg1, arg2 ) - symbols = [ - ',', '()', '[]', '!=', '%', '%=', '&', '&&', '&=', '*', '*=', '+', - '+=', '-', '-=', '->', '->*', '/', '/=', '<', '<<', '<<=', '<=', '=', - '==', '>', '>=', '>>', '>>=', '^', '^=', '|', '|=', '||'] - if not isinstance(oper, calldef_members.operator_t): - return False - if oper.symbol not in symbols: - return False - if isinstance(oper, calldef_members.member_operator_t): - if 1 == len(oper.arguments): - return True - else: - return False - else: - if 2 == len(oper.arguments): - return True - else: - return False - - -class __is_convertible_t(object): - - """implementation details""" - - def __init__(self, source, target): - self.__source = self.__normalize(source) - self.__target = self.__normalize(target) - - def __find_class_by_class_declaration(self, class_decl): - found = scopedef.find_declaration( - class_decl.parent.declarations, - name=class_decl.name, - decl_type=class_declaration.class_t) - return found - - def __normalize(self, type_): - type_ = type_traits_utils.remove_alias(type_) - bt_of_type = type_traits_utils.base_type(type_) - if isinstance(bt_of_type, cpptypes.declarated_t) \ - and isinstance(bt_of_type.declaration, - class_declaration.class_declaration_t): - type_ = type_.clone() - bt_of_type = type_traits_utils.base_type(type_) - bt_of_type.declaration = self.__find_class_by_class_declaration( - bt_of_type.declaration) - return type_ - - def __test_trivial(self, source, target): - if not (source and target): - return False - if is_same(source, target): - return True # X => X - if is_const(target) and is_same(source, target.base): - return True # X => const X - if is_reference(target) and is_same(source, target.base): - return True # X => X& - if is_reference(target) and is_const(target.base) and \ - is_same(source, target.base.base): - return True # X => const X& - if is_same(target, cpptypes.pointer_t(cpptypes.void_t())): - if is_integral(source) or is_enum(source): - return False - else: - return True # X => void* - if is_pointer(source) and is_pointer(target): - if is_const(target.base) and \ - is_same(source.base, target.base.base): - return True # X* => const X* - if is_reference(source) and is_reference(target): - if is_const(target.base) and \ - is_same(source.base, target.base.base): - return True # X& => const X& - if not is_const(source) and is_array(source) and is_pointer(target): - if is_same(type_traits_utils.base_type(source), target.base): - return True # X[2] => X* - if is_array(source) and is_pointer(target) and is_const(target.base): - if is_same(type_traits_utils.base_type(source), target.base.base): - return True - - def __test_pointer_to_func_or_mv__to__func_or_mv(self, source, target): - if is_pointer(source) \ - and is_reference(target) \ - and isinstance(target.base, - (cpptypes.free_function_type_t, - cpptypes.member_function_type_t, - cpptypes.member_variable_type_t)) \ - and is_same(source.base, target.base): - return True - - if is_pointer(source) \ - and isinstance(target, - (cpptypes.free_function_type_t, - cpptypes.member_function_type_t, - cpptypes.member_variable_type_t)) \ - and is_same(source.base, target): - return True - - if is_pointer(target) \ - and is_reference(source) \ - and isinstance(source.base, - (cpptypes.free_function_type_t, - cpptypes.member_function_type_t, - cpptypes.member_variable_type_t)) \ - and is_same(source.base, target.base): - return True - - if is_pointer(target) \ - and isinstance(source, - (cpptypes.free_function_type_t, - cpptypes.member_function_type_t, - cpptypes.member_variable_type_t)) \ - and is_same(target.base, source): - return True - - def __test_const_x_ref__to__x(self, source, target): - if not is_reference(source) \ - or not is_const(source.base) \ - or not is_same(source.base.base, target): - return False - if is_fundamental(target): - return True - if is_enum(target): - return True - if isinstance(target, cpptypes.declarated_t): - assert isinstance(target.declaration, class_declaration.class_t) - if has_copy_constructor(target.declaration): - return True # we have copy constructor - return False - - def __test_const_ref_x__to__y(self, source, target): - if not is_reference(source) or not is_const(source.base): - return False - if is_fundamental(source.base.base) and is_fundamental(target): - return True - if is_convertible(source.base.base, cpptypes.int_t()) and \ - is_enum(target): - return True - if isinstance(target, cpptypes.declarated_t): - assert isinstance(target.declaration, class_declaration.class_t) - if has_copy_constructor(target.declaration): - return True # we have copy constructor - return False - - def __test_ref_x__to__x(self, source, target): - if not is_reference(source) or not is_same(source.base, target): - return False - if is_fundamental(target): - return True - if is_enum(target): - return True - if isinstance(target, cpptypes.declarated_t): - assert isinstance(target.declaration, class_declaration.class_t) - if has_copy_constructor(target.declaration): - return True # we have copy constructor - return False - - def __test_ref_x__to__y(self, source, target): - if not is_reference(source): - return False - if is_fundamental(source.base) and is_fundamental(target): - return True - if is_convertible(source.base, cpptypes.int_t()) and is_enum(target): - return True - if isinstance(target, cpptypes.declarated_t): - assert isinstance(target.declaration, class_declaration.class_t) - if has_copy_constructor(target.declaration): - return True # we have copy constructor - return False - - def __test_fundamental__to__fundamental(self, source, target): - if not is_fundamental(type_traits_utils.base_type(source)) or not \ - is_fundamental(type_traits_utils.base_type(target)): - return False - if is_void(type_traits_utils.base_type(source)) or \ - is_void(type_traits_utils.base_type(target)): - return False - if is_fundamental(source) and is_fundamental(target): - return True - if not is_pointer(source) and is_fundamental(target): - return True - if not is_pointer(source) and is_const(target) and\ - is_fundamental(target.base): - return True - if is_fundamental(source) \ - and is_reference(target) \ - and is_const(target.base) \ - and is_fundamental(target.base.base): - return True # X => const Y& - return False - - def _is_both_declarated(self, x, y): - return ( - isinstance(x, cpptypes.declarated_t) and - isinstance(y, cpptypes.declarated_t)) - - def __test_derived_to_based(self, source, target): - derived = type_traits_utils.base_type(source) - base = type_traits_utils.base_type(target) - if not ( - isinstance(derived, cpptypes.declarated_t) and - isinstance(derived.declaration, class_declaration.class_t)): - return False - if not (isinstance(base, cpptypes.declarated_t) and - isinstance(base.declaration, class_declaration.class_t)): - return False - base = base.declaration - derived = derived.declaration - if not is_base_and_derived(base, derived): - return False - for b in derived.recursive_bases: - if ((b.related_class is base) and b.access_type != - class_declaration.ACCESS_TYPES.PRIVATE): - break - else: - return False - - base = target - derived = source - # d => b - if self._is_both_declarated(base, derived): - return True - # d* => b* - if is_pointer(derived) and is_pointer(base) \ - and self._is_both_declarated(base.base, derived.base): - return True - # const d* => const b* - if is_pointer(derived) and is_pointer(base) \ - and is_const(derived.base) and is_const(base.base) \ - and self._is_both_declarated(base.base.base, derived.base.base): - return True - # d* => const b* - if is_pointer(derived) and is_pointer(base) \ - and is_const(derived.base)\ - and self._is_both_declarated(base.base.base, derived.base): - return True - - # d& => b& - if is_reference(derived) and is_reference(base) \ - and self._is_both_declarated(base.base, derived.base): - return True - # const d& => const b& - if is_reference(derived) and is_reference(base) \ - and is_const(derived.base) and is_const(base.base) \ - and self._is_both_declarated(base.base.base, derived.base.base): - return True - # d& => const b& - if is_reference(derived) and is_reference(base) \ - and is_const(derived.base) \ - and self._is_both_declarated(base.base.base, derived.base): - return True - return False - - def is_convertible(self): - source = self.__source - target = self.__target - - if self.__test_trivial(source, target): - return True - if is_array(source) or is_array(target): - return False - if self.__test_const_x_ref__to__x(source, target): - return True - if self.__test_const_ref_x__to__y(source, target): - return True - if self.__test_ref_x__to__x(source, target): - return True - if self.__test_ref_x__to__y(source, target): - return True - if self.__test_fundamental__to__fundamental(source, target): - return True - if self.__test_pointer_to_func_or_mv__to__func_or_mv(source, target): - return True - if self.__test_derived_to_based(source, target): - return True - - if isinstance(source, cpptypes.declarated_t): - if isinstance(source.declaration, enumeration.enumeration_t) \ - and is_fundamental(target) \ - and not is_void(target): - return True # enum could be converted to any integral type - - if isinstance(source.declaration, class_declaration.class_t): - source_inst = source.declaration - # class instance could be convertible to something else if it - # has operator - casting_operators = scopedef.find_all_declarations( - source_inst.declarations, - decl_type=calldef_members.casting_operator_t, - recursive=False) - if casting_operators: - for operator in casting_operators: - if is_convertible(operator.return_type, target): - return True - - # may be target is class too, so in this case we should check whether - # is has constructor from source - if isinstance(target, cpptypes.declarated_t): - if isinstance(target.declaration, class_declaration.class_t): - constructors = scopedef.find_all_declarations( - target.declaration.declarations, - decl_type=calldef_members.constructor_t, - recursive=False) - if constructors: - for constructor in constructors: - if 1 != len(constructor.arguments): - continue - # TODO: add test to check explicitness - if is_convertible(source, - constructor.arguments[0].decl_type): - return True - - return False - - -def is_convertible(source, target): - """returns True, if source could be converted to target, otherwise False""" - return __is_convertible_t(source, target).is_convertible() - - -def __is_noncopyable_single(class_): - """implementation details""" - # It is not enough to check base classes, we should also to check - # member variables. - logger = utils.loggers.cxx_parser - - if has_copy_constructor(class_) \ - and has_public_constructor(class_) \ - and has_public_assign(class_) \ - and has_public_destructor(class_): - msg = os.linesep.join([ - "__is_noncopyable_single - %s - COPYABLE:" % class_.decl_string, - " trivial copy constructor: yes", - " public constructor: yes", - " public assign: yes", - " public destructor: yes"]) - logger.debug(msg) - return False - if find_noncopyable_vars(class_): - logger.debug( - ("__is_noncopyable_single(TRUE) - %s - contains noncopyable " + - "members") % class_.decl_string) - return True - else: - logger.debug(( - "__is_noncopyable_single(FALSE) - %s - COPYABLE, because is " + - "doesn't contains noncopyable members") % class_.decl_string) - return False - - -def is_noncopyable(class_): - """returns True, if class is noncopyable, False otherwise""" - logger = utils.loggers.cxx_parser - class_decl = class_traits.get_declaration(class_) - - true_header = "is_noncopyable(TRUE) - %s - " % class_.decl_string - # false_header = "is_noncopyable(false) - %s - " % class_.decl_string - - if is_union(class_): - return False - - if class_decl.is_abstract: - logger.debug(true_header + "abstract client") - return True - - # if class has public, user defined copy constructor, than this class is - # copyable - copy_ = find_copy_constructor(class_decl) - if copy_ and copy_.access_type == 'public' and not copy_.is_artificial: - return False - - for base_desc in class_decl.recursive_bases: - assert isinstance(base_desc, class_declaration.hierarchy_info_t) - - if base_desc.related_class.decl_string in \ - ('::boost::noncopyable', '::boost::noncopyable_::noncopyable'): - logger.debug(true_header + "derives from boost::noncopyable") - return True - - if not has_copy_constructor(base_desc.related_class): - - base_copy_ = find_copy_constructor(base_desc.related_class) - - if base_copy_: - - if base_copy_.access_type == 'private': - logger.debug( - true_header + - "there is private copy constructor") - return True - else: - if __is_noncopyable_single(base_desc.related_class): - logger.debug( - true_header + - "__is_noncopyable_single returned True") - return True - - if __is_noncopyable_single(base_desc.related_class): - logger.debug( - true_header + - "__is_noncopyable_single returned True") - return True - - if not has_copy_constructor(class_decl): - logger.debug(true_header + "does not have trivial copy constructor") - return True - elif not has_public_constructor(class_decl): - logger.debug(true_header + "does not have a public constructor") - return True - elif has_destructor(class_decl) and not has_public_destructor(class_decl): - logger.debug(true_header + "has private destructor") - return True - else: - return __is_noncopyable_single(class_decl) - - def is_defined_in_xxx(xxx, cls): """ small helper function, that checks whether the class `cls` is defined @@ -1100,171 +370,6 @@ def is_defined_in_xxx(xxx, cls): return None is global_ns.parent -class impl_details(object): - - """implementation details""" - @staticmethod - def is_defined_in_xxx(xxx, cls): - """implementation details""" - if not cls.parent: - return False - - if not isinstance(cls.parent, namespace.namespace_t): - return False - - if xxx != cls.parent.name: - return False - - xxx_ns = cls.parent - if not xxx_ns.parent: - return False - - if not isinstance(xxx_ns.parent, namespace.namespace_t): - return False - - if '::' != xxx_ns.parent.name: - return False - - global_ns = xxx_ns.parent - return None is global_ns.parent - - @staticmethod - def find_value_type(global_ns, value_type_str): - """implementation details""" - if not value_type_str.startswith('::'): - value_type_str = '::' + value_type_str - found = global_ns.decls( - name=value_type_str, - function=lambda decl: not isinstance(decl, calldef.calldef_t), - allow_empty=True) - if not found: - no_global_ns_value_type_str = value_type_str[2:] - if no_global_ns_value_type_str in cpptypes.FUNDAMENTAL_TYPES: - return cpptypes.FUNDAMENTAL_TYPES[no_global_ns_value_type_str] - elif is_std_string(value_type_str): - string_ = global_ns.typedef('::std::string') - return remove_declarated(string_) - elif is_std_wstring(value_type_str): - string_ = global_ns.typedef('::std::wstring') - return remove_declarated(string_) - else: - value_type_str = no_global_ns_value_type_str - has_const = value_type_str.startswith('const ') - if has_const: - value_type_str = value_type_str[len('const '):] - has_pointer = value_type_str.endswith('*') - if has_pointer: - value_type_str = value_type_str[:-1] - found = None - if has_const or has_pointer: - found = impl_details.find_value_type( - global_ns, - value_type_str) - if not found: - return None - else: - if isinstance(found, class_declaration.class_types): - found = cpptypes.declarated_t(found) - if has_const: - found = cpptypes.const_t(found) - if has_pointer: - found = cpptypes.pointer_t(found) - return found - if len(found) == 1: - return found[0] - else: - return None - - -class internal_type_traits(object): - - """small convenience class, which provides access to internal types""" - # TODO: add exists function - @staticmethod - def get_by_name(type_, name): - if class_traits.is_my_case(type_): - cls = class_traits.declaration_class(type_) - return remove_declarated( - cls.typedef(name, recursive=False).decl_type) - elif class_declaration_traits.is_my_case(type_): - cls = class_declaration_traits.get_declaration(type_) - value_type_str = templates.args(cls.name)[0] - ref = impl_details.find_value_type(cls.top_parent, value_type_str) - if ref: - return ref - else: - raise RuntimeError(( - "Unable to find reference to internal " + - "type '%s' in type '%s'.") % (name, cls.decl_string)) - else: - raise RuntimeError(( - "Unable to find reference to internal type '%s' in type '%s'.") - % (name, type_.decl_string)) - - -class smart_pointer_traits(object): - - """implements functionality, needed for convenient work with - smart pointers""" - - @staticmethod - def is_smart_pointer(type_): - """returns True, if type represents instantiation of - `boost::shared_ptr` or `std::shared_ptr`, False otherwise""" - type_ = type_traits_utils.remove_alias(type_) - type_ = remove_cv(type_) - type_ = remove_declarated(type_) - if not isinstance(type_, - (class_declaration.class_declaration_t, - class_declaration.class_t)): - return False - if not (impl_details.is_defined_in_xxx('boost', type_) or - impl_details.is_defined_in_xxx('std', type_)): - return False - return type_.decl_string.startswith('::boost::shared_ptr<') or \ - type_.decl_string.startswith('::std::shared_ptr<') - - @staticmethod - def value_type(type_): - """returns reference to `boost::shared_ptr` \ - or `std::shared_ptr` value type""" - if not smart_pointer_traits.is_smart_pointer(type_): - raise TypeError( - 'Type "%s" is not an instantiation of \ - boost::shared_ptr or std::shared_ptr' % - type_.decl_string) - return internal_type_traits.get_by_name(type_, "value_type") - - -class auto_ptr_traits(object): - - """implements functionality, needed for convenient work with - `std::auto_ptr` pointers""" - - @staticmethod - def is_smart_pointer(type_): - """returns True, if type represents instantiation of - `boost::shared_ptr`, False otherwise""" - type_ = type_traits_utils.remove_alias(type_) - type_ = remove_cv(type_) - type_ = remove_declarated(type_) - if not isinstance(type_, - (class_declaration.class_declaration_t, - class_declaration.class_t)): - return False - if not impl_details.is_defined_in_xxx('std', type_): - return False - return type_.decl_string.startswith('::std::auto_ptr<') - - @staticmethod - def value_type(type_): - """returns reference to `boost::shared_ptr` value type""" - if not auto_ptr_traits.is_smart_pointer(type_): - raise TypeError( - 'Type "%s" is not instantiation of std::auto_ptr' % - type_.decl_string) - return internal_type_traits.get_by_name(type_, "element_type") - string_equivalences = [ ('::std::basic_string,' + 'std::allocator >'), @@ -1340,75 +445,3 @@ def is_std_wostream(type_): else: type_ = type_traits_utils.remove_alias(type_) return remove_cv(type_).decl_string in wostream_equivalences - - -def is_copy_constructor(constructor): - """ - Check if the declaration is a copy constructor, - - Args: - constructor (declarations.constructor_t): the constructor - to be checked. - - Returns: - bool: True if this is a copy constructor, False instead. - - """ - assert (isinstance(constructor, calldef_members.constructor_t)) - args = constructor.arguments - parent = constructor.parent - - # A copy constructor has only one argument - if len(args) != 1: - return False - - # We have only one argument, get it - arg = args[0] - - if not isinstance(arg.decl_type, cpptypes.compound_t): - # An argument of type declarated_t (a typedef) could be passed to - # the constructor; and it could be a reference. - # But in c++ you can NOT write : - # "typedef class MyClass { MyClass(const MyClass & arg) {} }" - # If the argument is a typedef, this is not a copy constructor. - # See the hierarchy of declarated_t and coumpound_t. They both - # inherit from type_t but are not related so we can discriminate - # between them. - return False - - # The argument needs to be passed by reference in a copy constructor - if not is_reference(arg.decl_type): - return False - - # The argument needs to be const for a copy constructor - if not is_const(arg.decl_type.base): - return False - - un_aliased = type_traits_utils.remove_alias(arg.decl_type.base) - # un_aliased now refers to const_t instance - if not isinstance(un_aliased.base, cpptypes.declarated_t): - # We are looking for a declaration - # If "class MyClass { MyClass(const int & arg) {} }" is used, - # this is not copy constructor, so we return False here. - # -> un_aliased.base == cpptypes.int_t (!= cpptypes.declarated_t) - return False - - # Final check: compare the parent (the class declaration for example) - # with the declaration of the type passed as argument. - return id(un_aliased.base.declaration) == id(parent) - - -def is_trivial_constructor(constructor): - """ - Check if the declaration is a trivial constructor. - - Args: - constructor (declarations.constructor_t): the constructor - to be checked. - - Returns: - bool: True if this is a trivial constructor, False instead. - - """ - assert(isinstance(constructor, calldef_members.constructor_t)) - return not bool(constructor.arguments) diff --git a/pygccxml/declarations/type_traits_classes.py b/pygccxml/declarations/type_traits_classes.py new file mode 100644 index 00000000..c868f17e --- /dev/null +++ b/pygccxml/declarations/type_traits_classes.py @@ -0,0 +1,837 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +import os + +from . import class_declaration +from . import type_traits +from . import type_traits_utils +from . import enumeration +from . import calldef_members +from . import calldef_types +from . import scopedef +from . import cpptypes +from .. import utils + + +def is_union(type_): + """returns True if type represents a C++ union""" + if not is_class(type_): + return False + decl = class_traits.get_declaration(type_) + return decl.class_type == class_declaration.CLASS_TYPES.UNION + + +class declaration_xxx_traits(object): + """this class implements the functionality needed for convenient work with + declaration classes + + Implemented functionality: + - find out whether a declaration is a desired one + - get reference to the declaration + """ + sequence = [ + type_traits_utils.remove_alias, + type_traits.remove_cv, + type_traits.remove_declarated] + + def __init__(self, declaration_class): + self.declaration_class = declaration_class + + def __apply_sequence(self, type_): + for f in self.sequence: + type_ = f(type_) + return type_ + + def is_my_case(self, type_): + """returns True, if type represents the desired declaration, + False otherwise""" + return ( + isinstance(self.__apply_sequence(type_), self.declaration_class) + ) + + def get_declaration(self, type_): + """returns reference to the declaration + + Precondition: self.is_my_case( type ) == True + """ + return self.__apply_sequence(type_) + +enum_traits = declaration_xxx_traits(enumeration.enumeration_t) +"""implements functionality, needed for convenient work with C++ enums""" + +is_enum = enum_traits.is_my_case +"""returns True, if type represents C++ enumeration declaration, +False otherwise""" + +enum_declaration = enum_traits.get_declaration +"""returns reference to enum declaration""" + +class_traits = declaration_xxx_traits(class_declaration.class_t) +"""implements functionality, needed for convenient work with C++ classes""" + +is_class = class_traits.is_my_case +"""returns True, if type represents C++ class definition, False otherwise""" + +class_declaration_traits = declaration_xxx_traits( + class_declaration.class_declaration_t) +"""implements functionality, needed for convenient work with C++ class +declarations""" + +is_class_declaration = class_declaration_traits.is_my_case +"""returns True, if type represents C++ class declaration, False otherwise""" + + +def find_trivial_constructor(type_): + """ + Returns reference to trivial constructor. + + Args: + type_ (declarations.class_t): the class to be searched. + + Returns: + declarations.constructor_t: the trivial constructor + + """ + assert isinstance(type_, class_declaration.class_t) + + trivial = type_.constructors( + lambda x: is_trivial_constructor(x), + recursive=False, + allow_empty=True) + if trivial: + return trivial[0] + else: + return None + + +def find_copy_constructor(type_): + """ + Returns reference to copy constructor. + + Args: + type_ (declarations.class_t): the class to be searched. + + Returns: + declarations.constructor_t: the copy constructor + + """ + copy_ = type_.constructors( + lambda x: is_copy_constructor(x), + recursive=False, + allow_empty=True) + if copy_: + return copy_[0] + else: + return None + + +def find_noncopyable_vars(type_): + """ + Returns list of all `noncopyable` variables. + + Args: + type_ (declarations.class_t): the class to be searched. + + Returns: + list: list of all `noncopyable` variables. + + """ + assert(isinstance(type_, class_declaration.class_t)) + + logger = utils.loggers.cxx_parser + mvars = type_.variables( + lambda v: not v.type_qualifiers.has_static, + recursive=False, + allow_empty=True) + noncopyable_vars = [] + + message = ( + "__contains_noncopyable_mem_var - %s - TRUE - " + + "contains const member variable") + + for mvar in mvars: + + type_ = type_traits.remove_reference(mvar.decl_type) + + if type_traits.is_const(type_): + no_const = type_traits.remove_const(type_) + if type_traits.is_fundamental(no_const) or is_enum(no_const): + logger.debug((message + "- fundamental or enum") + % type_.decl_string) + noncopyable_vars.append(mvar) + if is_class(no_const): + logger.debug((message + " - class") % type_.decl_string) + noncopyable_vars.append(mvar) + if type_traits.is_array(no_const): + logger.debug((message + " - array") % type_.decl_string) + noncopyable_vars.append(mvar) + + if class_traits.is_my_case(type_): + + cls = class_traits.get_declaration(type_) + if is_noncopyable(cls): + logger.debug((message + " - class that is not copyable") + % type_.decl_string) + noncopyable_vars.append(mvar) + + logger.debug( + ("__contains_noncopyable_mem_var - %s - FALSE - doesn't " + + "contain noncopyable members") % type_.decl_string) + + return noncopyable_vars + + +def has_trivial_constructor(class_): + """if class has public trivial constructor, this function will return + reference to it, None otherwise""" + class_ = class_traits.get_declaration(class_) + trivial = find_trivial_constructor(class_) + if trivial and trivial.access_type == 'public': + return trivial + + +def has_copy_constructor(class_): + """if class has public copy constructor, this function will return + reference to it, None otherwise""" + class_ = class_traits.get_declaration(class_) + copy_constructor = find_copy_constructor(class_) + if copy_constructor and copy_constructor.access_type == 'public': + return copy_constructor + + +def has_destructor(class_): + """if class has destructor, this function will return reference to it, + None otherwise""" + class_ = class_traits.get_declaration(class_) + destructor = class_.decls( + decl_type=calldef_members.destructor_t, + recursive=False, + allow_empty=True) + if destructor: + return destructor[0] + + +def has_public_constructor(class_): + """if class has any public constructor, this function will return list of + them, otherwise None""" + class_ = class_traits.get_declaration(class_) + decls = class_.constructors( + lambda c: not is_copy_constructor(c) and c.access_type == 'public', + recursive=False, + allow_empty=True) + if decls: + return decls + + +def has_public_assign(class_): + """returns True, if class has public assign operator, False otherwise""" + class_ = class_traits.get_declaration(class_) + decls = class_.mem_opers( + lambda o: o.symbol == '=' and o.access_type == 'public', + recursive=False, + allow_empty=True) + return bool(decls) + + +def has_public_destructor(type): + """returns True, if class has public destructor, False otherwise""" + d = has_destructor(type) + return d and d.access_type == 'public' + + +def has_vtable(type_): + """True, if class has virtual table, False otherwise""" + assert(isinstance(type_, class_declaration.class_t)) + return bool( + type_.calldefs( + lambda f: isinstance(f, calldef_members.member_function_t) and + f.virtuality != calldef_types.VIRTUALITY_TYPES.NOT_VIRTUAL, + recursive=False, + allow_empty=True)) + + +def is_base_and_derived(based, derived): + """returns True, if there is "base and derived" relationship between + classes, False otherwise""" + assert isinstance(based, class_declaration.class_t) + assert isinstance(derived, (class_declaration.class_t, tuple)) + + if isinstance(derived, class_declaration.class_t): + all_derived = ([derived]) + else: # tuple + all_derived = derived + + for derived_cls in all_derived: + for base_desc in derived_cls.recursive_bases: + if base_desc.related_class == based: + return True + return False + + +def has_any_non_copyconstructor(type): + """if class has any public constructor, which is not copy constructor, + this function will return list of them, otherwise None""" + class_ = class_traits.get_declaration(type) + decls = class_.constructors( + lambda c: not is_copy_constructor(c) and c.access_type == 'public', + recursive=False, + allow_empty=True) + if decls: + return decls + + +class __is_convertible_t(object): + + """implementation details""" + + def __init__(self, source, target): + self.__source = self.__normalize(source) + self.__target = self.__normalize(target) + + def __find_class_by_class_declaration(self, class_decl): + found = scopedef.find_declaration( + class_decl.parent.declarations, + name=class_decl.name, + decl_type=class_declaration.class_t) + return found + + def __normalize(self, type_): + type_ = type_traits_utils.remove_alias(type_) + bt_of_type = type_traits_utils.base_type(type_) + if isinstance(bt_of_type, cpptypes.declarated_t) \ + and isinstance(bt_of_type.declaration, + class_declaration.class_declaration_t): + type_ = type_.clone() + bt_of_type = type_traits_utils.base_type(type_) + bt_of_type.declaration = self.__find_class_by_class_declaration( + bt_of_type.declaration) + return type_ + + def __test_trivial(self, source, target): + if not (source and target): + return False + if type_traits.is_same(source, target): + return True # X => X + if type_traits.is_const(target) and type_traits.is_same( + source, target.base): + return True # X => const X + if type_traits.is_reference(target) and type_traits.is_same( + source, target.base): + return True # X => X& + if type_traits.is_reference(target) and type_traits.is_const( + target.base) and type_traits.is_same(source, target.base.base): + return True # X => const X& + if type_traits.is_same(target, cpptypes.pointer_t(cpptypes.void_t())): + if type_traits.is_integral(source) or is_enum(source): + return False + else: + return True # X => void* + if type_traits.is_pointer(source) and type_traits.is_pointer(target): + if type_traits.is_const(target.base) and \ + type_traits.is_same(source.base, target.base.base): + return True # X* => const X* + if type_traits.is_reference(source) and \ + type_traits.is_reference(target): + if type_traits.is_const(target.base) and \ + type_traits.is_same(source.base, target.base.base): + return True # X& => const X& + if not type_traits.is_const(source) and \ + type_traits.is_array(source) and \ + type_traits.is_pointer(target): + if type_traits.is_same( + type_traits_utils.base_type(source), target.base): + return True # X[2] => X* + if type_traits.is_array(source) and \ + type_traits.is_pointer(target) and \ + type_traits.is_const(target.base): + if type_traits.is_same( + type_traits_utils.base_type(source), target.base.base): + return True + + def __test_pointer_to_func_or_mv__to__func_or_mv(self, source, target): + if type_traits.is_pointer(source) \ + and type_traits.is_reference(target) \ + and isinstance(target.base, + (cpptypes.free_function_type_t, + cpptypes.member_function_type_t, + cpptypes.member_variable_type_t)) \ + and type_traits.is_same(source.base, target.base): + return True + + if type_traits.is_pointer(source) \ + and isinstance(target, + (cpptypes.free_function_type_t, + cpptypes.member_function_type_t, + cpptypes.member_variable_type_t)) \ + and type_traits.is_same(source.base, target): + return True + + if type_traits.is_pointer(target) \ + and type_traits.is_reference(source) \ + and isinstance(source.base, + (cpptypes.free_function_type_t, + cpptypes.member_function_type_t, + cpptypes.member_variable_type_t)) \ + and type_traits.is_same(source.base, target.base): + return True + + if type_traits.is_pointer(target) \ + and isinstance(source, + (cpptypes.free_function_type_t, + cpptypes.member_function_type_t, + cpptypes.member_variable_type_t)) \ + and type_traits.is_same(target.base, source): + return True + + def __test_const_x_ref__to__x(self, source, target): + if not type_traits.is_reference(source) \ + or not type_traits.is_const(source.base) \ + or not type_traits.is_same(source.base.base, target): + return False + if type_traits.is_fundamental(target): + return True + if is_enum(target): + return True + if isinstance(target, cpptypes.declarated_t): + assert isinstance(target.declaration, class_declaration.class_t) + if has_copy_constructor(target.declaration): + return True # we have copy constructor + return False + + def __test_const_ref_x__to__y(self, source, target): + if not type_traits.is_reference(source) or not \ + type_traits.is_const(source.base): + return False + if type_traits.is_fundamental(source.base.base) and \ + type_traits.is_fundamental(target): + return True + if is_convertible(source.base.base, cpptypes.int_t()) and \ + is_enum(target): + return True + if isinstance(target, cpptypes.declarated_t): + assert isinstance(target.declaration, class_declaration.class_t) + if has_copy_constructor(target.declaration): + return True # we have copy constructor + return False + + def __test_ref_x__to__x(self, source, target): + if not type_traits.is_reference(source) or not \ + type_traits.is_same(source.base, target): + return False + if type_traits.is_fundamental(target): + return True + if is_enum(target): + return True + if isinstance(target, cpptypes.declarated_t): + assert isinstance(target.declaration, class_declaration.class_t) + if has_copy_constructor(target.declaration): + return True # we have copy constructor + return False + + def __test_ref_x__to__y(self, source, target): + if not type_traits.is_reference(source): + return False + if type_traits.is_fundamental(source.base) and \ + type_traits.is_fundamental(target): + return True + if is_convertible(source.base, cpptypes.int_t()) and is_enum(target): + return True + if isinstance(target, cpptypes.declarated_t): + assert isinstance(target.declaration, class_declaration.class_t) + if has_copy_constructor(target.declaration): + return True # we have copy constructor + return False + + def __test_fundamental__to__fundamental(self, source, target): + if not type_traits.is_fundamental( + type_traits_utils.base_type(source)) or not \ + type_traits.is_fundamental( + type_traits_utils.base_type(target)): + return False + if type_traits.is_void(type_traits_utils.base_type(source)) or \ + type_traits.is_void(type_traits_utils.base_type(target)): + return False + if type_traits.is_fundamental(source) and \ + type_traits.is_fundamental(target): + return True + if not type_traits.is_pointer(source) and \ + type_traits.is_fundamental(target): + return True + if not type_traits.is_pointer(source) and \ + type_traits.is_const(target) and \ + type_traits.is_fundamental(target.base): + return True + if type_traits.is_fundamental(source) \ + and type_traits.is_reference(target) \ + and type_traits.is_const(target.base) \ + and type_traits.is_fundamental(target.base.base): + return True # X => const Y& + return False + + def _is_both_declarated(self, x, y): + return ( + isinstance(x, cpptypes.declarated_t) and + isinstance(y, cpptypes.declarated_t)) + + def __test_derived_to_based(self, source, target): + derived = type_traits_utils.base_type(source) + base = type_traits_utils.base_type(target) + if not ( + isinstance(derived, cpptypes.declarated_t) and + isinstance(derived.declaration, class_declaration.class_t)): + return False + if not (isinstance(base, cpptypes.declarated_t) and + isinstance(base.declaration, class_declaration.class_t)): + return False + base = base.declaration + derived = derived.declaration + if not is_base_and_derived(base, derived): + return False + for b in derived.recursive_bases: + if ((b.related_class is base) and b.access_type != + class_declaration.ACCESS_TYPES.PRIVATE): + break + else: + return False + + base = target + derived = source + # d => b + if self._is_both_declarated(base, derived): + return True + # d* => b* + if type_traits.is_pointer(derived) and \ + type_traits.is_pointer(base) and \ + self._is_both_declarated(base.base, derived.base): + return True + # const d* => const b* + if type_traits.is_pointer(derived) and \ + type_traits.is_pointer(base) and \ + type_traits.is_const(derived.base) and \ + type_traits.is_const(base.base) \ + and self._is_both_declarated(base.base.base, derived.base.base): + return True + # d* => const b* + if type_traits.is_pointer(derived) and type_traits.is_pointer(base) \ + and type_traits.is_const(derived.base)\ + and self._is_both_declarated(base.base.base, derived.base): + return True + + # d& => b& + if type_traits.is_reference(derived) and \ + type_traits.is_reference(base) and \ + self._is_both_declarated(base.base, derived.base): + return True + # const d& => const b& + if type_traits.is_reference(derived) and \ + type_traits.is_reference(base) and \ + type_traits.is_const(derived.base) and \ + type_traits.is_const(base.base) \ + and self._is_both_declarated(base.base.base, derived.base.base): + return True + # d& => const b& + if type_traits.is_reference(derived) and \ + type_traits.is_reference(base) and \ + type_traits.is_const(derived.base) \ + and self._is_both_declarated(base.base.base, derived.base): + return True + return False + + def is_convertible(self): + source = self.__source + target = self.__target + + if self.__test_trivial(source, target): + return True + if type_traits.is_array(source) or type_traits.is_array(target): + return False + if self.__test_const_x_ref__to__x(source, target): + return True + if self.__test_const_ref_x__to__y(source, target): + return True + if self.__test_ref_x__to__x(source, target): + return True + if self.__test_ref_x__to__y(source, target): + return True + if self.__test_fundamental__to__fundamental(source, target): + return True + if self.__test_pointer_to_func_or_mv__to__func_or_mv(source, target): + return True + if self.__test_derived_to_based(source, target): + return True + + if isinstance(source, cpptypes.declarated_t): + if isinstance(source.declaration, enumeration.enumeration_t) \ + and type_traits.is_fundamental(target) \ + and not type_traits.is_void(target): + return True # enum could be converted to any integral type + + if isinstance(source.declaration, class_declaration.class_t): + source_inst = source.declaration + # class instance could be convertible to something else if it + # has operator + casting_operators = scopedef.find_all_declarations( + source_inst.declarations, + decl_type=calldef_members.casting_operator_t, + recursive=False) + if casting_operators: + for operator in casting_operators: + if is_convertible(operator.return_type, target): + return True + + # may be target is class too, so in this case we should check whether + # is has constructor from source + if isinstance(target, cpptypes.declarated_t): + if isinstance(target.declaration, class_declaration.class_t): + constructors = scopedef.find_all_declarations( + target.declaration.declarations, + decl_type=calldef_members.constructor_t, + recursive=False) + if constructors: + for constructor in constructors: + if 1 != len(constructor.arguments): + continue + # TODO: add test to check explicitness + if is_convertible(source, + constructor.arguments[0].decl_type): + return True + + return False + + +def is_convertible(source, target): + """returns True, if source could be converted to target, otherwise False""" + return __is_convertible_t(source, target).is_convertible() + + +def __is_noncopyable_single(class_): + """implementation details""" + # It is not enough to check base classes, we should also to check + # member variables. + logger = utils.loggers.cxx_parser + + if has_copy_constructor(class_) \ + and has_public_constructor(class_) \ + and has_public_assign(class_) \ + and has_public_destructor(class_): + msg = os.linesep.join([ + "__is_noncopyable_single - %s - COPYABLE:" % class_.decl_string, + " trivial copy constructor: yes", + " public constructor: yes", + " public assign: yes", + " public destructor: yes"]) + logger.debug(msg) + return False + if find_noncopyable_vars(class_): + logger.debug( + ("__is_noncopyable_single(TRUE) - %s - contains noncopyable " + + "members") % class_.decl_string) + return True + else: + logger.debug(( + "__is_noncopyable_single(FALSE) - %s - COPYABLE, because is " + + "doesn't contains noncopyable members") % class_.decl_string) + return False + + +def is_noncopyable(class_): + """returns True, if class is noncopyable, False otherwise""" + logger = utils.loggers.cxx_parser + class_decl = class_traits.get_declaration(class_) + + true_header = "is_noncopyable(TRUE) - %s - " % class_.decl_string + # false_header = "is_noncopyable(false) - %s - " % class_.decl_string + + if is_union(class_): + return False + + if class_decl.is_abstract: + logger.debug(true_header + "abstract client") + return True + + # if class has public, user defined copy constructor, than this class is + # copyable + copy_ = find_copy_constructor(class_decl) + if copy_ and copy_.access_type == 'public' and not copy_.is_artificial: + return False + + for base_desc in class_decl.recursive_bases: + assert isinstance(base_desc, class_declaration.hierarchy_info_t) + + if base_desc.related_class.decl_string in \ + ('::boost::noncopyable', '::boost::noncopyable_::noncopyable'): + logger.debug(true_header + "derives from boost::noncopyable") + return True + + if not has_copy_constructor(base_desc.related_class): + + base_copy_ = find_copy_constructor(base_desc.related_class) + + if base_copy_: + + if base_copy_.access_type == 'private': + logger.debug( + true_header + + "there is private copy constructor") + return True + else: + if __is_noncopyable_single(base_desc.related_class): + logger.debug( + true_header + + "__is_noncopyable_single returned True") + return True + + if __is_noncopyable_single(base_desc.related_class): + logger.debug( + true_header + + "__is_noncopyable_single returned True") + return True + + if not has_copy_constructor(class_decl): + logger.debug(true_header + "does not have trivial copy constructor") + return True + elif not has_public_constructor(class_decl): + logger.debug(true_header + "does not have a public constructor") + return True + elif has_destructor(class_decl) and not has_public_destructor(class_decl): + logger.debug(true_header + "has private destructor") + return True + else: + return __is_noncopyable_single(class_decl) + + +def is_unary_operator(oper): + """returns True, if operator is unary operator, otherwise False""" + # definition: + # memeber in class + # ret-type operator symbol() + # ret-type operator [++ --](int) + # globally + # ret-type operator symbol( arg ) + # ret-type operator [++ --](X&, int) + symbols = ['!', '&', '~', '*', '+', '++', '-', '--'] + if not isinstance(oper, calldef_members.operator_t): + return False + if oper.symbol not in symbols: + return False + if isinstance(oper, calldef_members.member_operator_t): + if 0 == len(oper.arguments): + return True + elif oper.symbol in ['++', '--'] and \ + isinstance(oper.arguments[0].decl_type, cpptypes.int_t): + return True + else: + return False + else: + if 1 == len(oper.arguments): + return True + elif oper.symbol in ['++', '--'] \ + and 2 == len(oper.arguments) \ + and isinstance(oper.arguments[1].decl_type, cpptypes.int_t): + # may be I need to add additional check whether first argument is + # reference or not? + return True + else: + return False + + +def is_binary_operator(oper): + """returns True, if operator is binary operator, otherwise False""" + # definition: + # memeber in class + # ret-type operator symbol(arg) + # globally + # ret-type operator symbol( arg1, arg2 ) + symbols = [ + ',', '()', '[]', '!=', '%', '%=', '&', '&&', '&=', '*', '*=', '+', + '+=', '-', '-=', '->', '->*', '/', '/=', '<', '<<', '<<=', '<=', '=', + '==', '>', '>=', '>>', '>>=', '^', '^=', '|', '|=', '||'] + if not isinstance(oper, calldef_members.operator_t): + return False + if oper.symbol not in symbols: + return False + if isinstance(oper, calldef_members.member_operator_t): + if 1 == len(oper.arguments): + return True + else: + return False + else: + if 2 == len(oper.arguments): + return True + else: + return False + + +def is_copy_constructor(constructor): + """ + Check if the declaration is a copy constructor, + + Args: + constructor (declarations.constructor_t): the constructor + to be checked. + + Returns: + bool: True if this is a copy constructor, False instead. + + """ + assert (isinstance(constructor, calldef_members.constructor_t)) + args = constructor.arguments + parent = constructor.parent + + # A copy constructor has only one argument + if len(args) != 1: + return False + + # We have only one argument, get it + arg = args[0] + + if not isinstance(arg.decl_type, cpptypes.compound_t): + # An argument of type declarated_t (a typedef) could be passed to + # the constructor; and it could be a reference. + # But in c++ you can NOT write : + # "typedef class MyClass { MyClass(const MyClass & arg) {} }" + # If the argument is a typedef, this is not a copy constructor. + # See the hierarchy of declarated_t and coumpound_t. They both + # inherit from type_t but are not related so we can discriminate + # between them. + return False + + # The argument needs to be passed by reference in a copy constructor + if not type_traits.is_reference(arg.decl_type): + return False + + # The argument needs to be const for a copy constructor + if not type_traits.is_const(arg.decl_type.base): + return False + + un_aliased = type_traits_utils.remove_alias(arg.decl_type.base) + # un_aliased now refers to const_t instance + if not isinstance(un_aliased.base, cpptypes.declarated_t): + # We are looking for a declaration + # If "class MyClass { MyClass(const int & arg) {} }" is used, + # this is not copy constructor, so we return False here. + # -> un_aliased.base == cpptypes.int_t (!= cpptypes.declarated_t) + return False + + # Final check: compare the parent (the class declaration for example) + # with the declaration of the type passed as argument. + return id(un_aliased.base.declaration) == id(parent) + + +def is_trivial_constructor(constructor): + """ + Check if the declaration is a trivial constructor. + + Args: + constructor (declarations.constructor_t): the constructor + to be checked. + + Returns: + bool: True if this is a trivial constructor, False instead. + + """ + assert (isinstance(constructor, calldef_members.constructor_t)) + return not bool(constructor.arguments) diff --git a/unittests/unnamed_classes_tester.py b/unittests/unnamed_classes_tester.py index d04a1dd5..d57d95ee 100644 --- a/unittests/unnamed_classes_tester.py +++ b/unittests/unnamed_classes_tester.py @@ -31,12 +31,12 @@ def validate_bitfields(self, parent, bitfields): def do_union_test(self, union_name, bitfields): s2 = self.global_ns.class_('S2') - self.assertFalse(type_traits.is_union(s2)) + self.assertFalse(declarations.is_union(s2)) self.assertEqual(s2.parent.name, 'S1') - self.assertFalse(type_traits.is_union(s2.parent)) + self.assertFalse(declarations.is_union(s2.parent)) union = s2.variable(union_name) - self.assertTrue(type_traits.is_union(union.decl_type)) + self.assertTrue(declarations.is_union(union.decl_type)) union_type = type_traits.remove_declarated(union.decl_type) self.validate_bitfields(union_type, bitfields) @@ -81,7 +81,7 @@ def test_anonymous_unions(self): s3_vars = ['anon_mem_c', 'anon_mem_i', 's3_mem', 's2'] for var in s3_vars: - self.assertFalse(type_traits.is_union(s3.variable(var).decl_type)) + self.assertFalse(declarations.is_union(s3.variable(var).decl_type)) def create_suite(): From fb5aa81a91b97fd57b43f6b21e0c2ebfef2a9667 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 7 Jun 2016 22:04:46 +0200 Subject: [PATCH 175/268] Move the functions from type_traits_utils to type_traits Now that the situation has cleared up, these methods belong back in the type_traits module. They were first extracted in a separate module to try to solve some cyclic dependencies. Now that these are solved and the concept stands, the functions can be moved back. --- pygccxml/declarations/__init__.py | 10 +- pygccxml/declarations/calldef.py | 4 +- pygccxml/declarations/class_declaration.py | 6 +- pygccxml/declarations/container_traits.py | 9 +- pygccxml/declarations/has_operator_matcher.py | 3 +- pygccxml/declarations/type_traits.py | 106 ++++++++++++++---- pygccxml/declarations/type_traits_classes.py | 27 +++-- pygccxml/declarations/type_traits_utils.py | 67 ----------- pygccxml/parser/patcher.py | 6 +- 9 files changed, 114 insertions(+), 124 deletions(-) delete mode 100644 pygccxml/declarations/type_traits_utils.py diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 182415c8..885378ff 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -117,6 +117,10 @@ from .decl_visitor import decl_visitor_t from .type_visitor import type_visitor_t +from .type_traits import decompose_type +from .type_traits import decompose_class +from .type_traits import base_type + from .type_traits import is_bool from .type_traits import is_same from .type_traits import is_void @@ -145,6 +149,7 @@ from .type_traits import remove_volatile from .type_traits import remove_reference from .type_traits import remove_declarated +from .type_traits import remove_alias from .has_operator_matcher import has_public_binary_operator from .has_operator_matcher import has_public_equal @@ -206,11 +211,6 @@ from .function_traits import is_same_function -from .type_traits_utils import decompose_type -from .type_traits_utils import decompose_class -from .type_traits_utils import base_type -from .type_traits_utils import remove_alias - from . import templates from . import call_invocation diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index 46d63999..741202bb 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -22,7 +22,7 @@ from . import declaration from . import class_declaration from . import call_invocation -from . import type_traits_utils +from . import type_traits from . import calldef_types from .. import utils @@ -408,7 +408,7 @@ def demangled_name(self): demangled = self.demangled if self.return_type: - return_type = type_traits_utils.remove_alias( + return_type = type_traits.remove_alias( self.return_type).decl_string if return_type.startswith('::') and not \ diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index cab28fc5..411475f9 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -634,12 +634,12 @@ class impl_details(object): def dig_declarations(depend_on_it): # FIXME: prevent cyclic imports - from . import type_traits_utils + from . import type_traits if isinstance(depend_on_it, declaration.declaration_t): return [depend_on_it] - base_type = type_traits_utils.base_type( - type_traits_utils.remove_alias(depend_on_it)) + base_type = type_traits.base_type( + type_traits.remove_alias(depend_on_it)) if isinstance(base_type, cpptypes.declarated_t): return [base_type.declaration] elif isinstance(base_type, cpptypes.calldef_type_t): diff --git a/pygccxml/declarations/container_traits.py b/pygccxml/declarations/container_traits.py index cfa93594..079f1ad5 100644 --- a/pygccxml/declarations/container_traits.py +++ b/pygccxml/declarations/container_traits.py @@ -12,7 +12,6 @@ from . import cpptypes from . import templates from . import type_traits -from . import type_traits_utils from . import namespace from . import class_declaration from . import calldef @@ -385,14 +384,14 @@ def get_container_or_none(self, type_): """ - type_ = type_traits_utils.remove_alias(type_) + type_ = type_traits.remove_alias(type_) type_ = type_traits.remove_cv(type_) utils.loggers.queries_engine.debug( "Container traits: cleaned up search %s" % type_) if isinstance(type_, cpptypes.declarated_t): - cls_declaration = type_traits_utils.remove_alias(type_.declaration) + cls_declaration = type_traits.remove_alias(type_.declaration) elif isinstance(type_, class_declaration.class_t): cls_declaration = type_ elif isinstance(type_, class_declaration.class_declaration_t): @@ -818,7 +817,7 @@ class smart_pointer_traits(object): def is_smart_pointer(type_): """returns True, if type represents instantiation of `boost::shared_ptr` or `std::shared_ptr`, False otherwise""" - type_ = type_traits_utils.remove_alias(type_) + type_ = type_traits.remove_alias(type_) type_ = type_traits.remove_cv(type_) type_ = type_traits.remove_declarated(type_) if not isinstance(type_, @@ -852,7 +851,7 @@ class auto_ptr_traits(object): def is_smart_pointer(type_): """returns True, if type represents instantiation of `boost::shared_ptr`, False otherwise""" - type_ = type_traits_utils.remove_alias(type_) + type_ = type_traits.remove_alias(type_) type_ = type_traits.remove_cv(type_) type_ = type_traits.remove_declarated(type_) if not isinstance(type_, diff --git a/pygccxml/declarations/has_operator_matcher.py b/pygccxml/declarations/has_operator_matcher.py index 0c054015..e8ae9792 100644 --- a/pygccxml/declarations/has_operator_matcher.py +++ b/pygccxml/declarations/has_operator_matcher.py @@ -1,5 +1,4 @@ from . import type_traits -from . import type_traits_utils from . import class_declaration from . import matchers from . import cpptypes @@ -7,7 +6,7 @@ def has_public_binary_operator(type_, operator_symbol): """returns True, if `type_` has public binary operator, otherwise False""" - type_ = type_traits_utils.remove_alias(type_) + type_ = type_traits.remove_alias(type_) type_ = type_traits.remove_cv(type_) type_ = type_traits.remove_declarated(type_) assert isinstance(type_, class_declaration.class_t) diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index be30f075..f174c436 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -19,11 +19,71 @@ """ from . import cpptypes +from . import typedef from . import namespace -from . import type_traits_utils from .. import utils +def __remove_alias(type_): + """implementation details""" + if isinstance(type_, typedef.typedef_t): + return __remove_alias(type_.decl_type) + if isinstance(type_, cpptypes.declarated_t) and \ + isinstance(type_.declaration, typedef.typedef_t): + return __remove_alias(type_.declaration.decl_type) + if isinstance(type_, cpptypes.compound_t): + type_.base = __remove_alias(type_.base) + return type_ + return type_ + + +def remove_alias(type_): + """returns type without typedefs""" + type_ref = None + if isinstance(type_, cpptypes.type_t): + type_ref = type_ + elif isinstance(type_, typedef.typedef_t): + type_ref = type_.decl_type + else: + pass # not a valid input, just return it + if not type_ref: + return type_ + if type_ref.cache.remove_alias: + return type_ref.cache.remove_alias + no_alias = __remove_alias(type_ref.clone()) + type_ref.cache.remove_alias = no_alias + return no_alias + + +def decompose_type(tp): + """implementation details""" + # implementation of this function is important + if isinstance(tp, cpptypes.compound_t): + return [tp] + decompose_type(tp.base) + elif isinstance(tp, typedef.typedef_t): + return decompose_type(tp.decl_type) + elif isinstance(tp, cpptypes.declarated_t) and \ + isinstance(tp.declaration, typedef.typedef_t): + return decompose_type(tp.declaration.decl_type) + else: + return [tp] + + +def decompose_class(type): + """implementation details""" + types = decompose_type(type) + return [tp.__class__ for tp in types] + + +def base_type(type): + """returns base type. + + For `const int` will return `int` + """ + types = decompose_type(type) + return types[-1] + + def create_cv_types(base): """implementation details""" return ( @@ -39,7 +99,7 @@ def does_match_definition(given, main, secondary): """implementation details""" assert isinstance(secondary, tuple) assert 2 == len(secondary) # general solution could be provided - types = type_traits_utils.decompose_type(given) + types = decompose_type(given) if isinstance(types[0], main): return True elif 2 <= len(types) and \ @@ -65,13 +125,13 @@ def does_match_definition(given, main, secondary): def is_bool(type_): """returns True, if type represents `bool`, False otherwise""" - return type_traits_utils.remove_alias(type_) in create_cv_types( + return remove_alias(type_) in create_cv_types( cpptypes.bool_t()) def is_void(type): """returns True, if type represents `void`, False otherwise""" - return type_traits_utils.remove_alias(type) in create_cv_types( + return remove_alias(type) in create_cv_types( cpptypes.void_t()) @@ -99,7 +159,7 @@ def is_integral(type): create_cv_types(cpptypes.int128_t()) + create_cv_types(cpptypes.uint128_t())) - return type_traits_utils.remove_alias(type) in integral_def + return remove_alias(type) in integral_def def is_floating_point(type): @@ -110,7 +170,7 @@ def is_floating_point(type): create_cv_types(cpptypes.double_t()) + create_cv_types(cpptypes.long_double_t())) - return type_traits_utils.remove_alias(type) in float_def + return remove_alias(type) in float_def def is_arithmetic(type): @@ -134,7 +194,7 @@ def is_calldef_pointer(type): False otherwise""" if not is_pointer(type): return False - nake_type = type_traits_utils.remove_alias(type) + nake_type = remove_alias(type) nake_type = remove_cv(nake_type) return isinstance(nake_type, cpptypes.compound_t) \ and isinstance(nake_type.base, cpptypes.calldef_type_t) @@ -145,7 +205,7 @@ def remove_pointer(type): If type is not pointer type, it will be returned as is. """ - nake_type = type_traits_utils.remove_alias(type) + nake_type = remove_alias(type) if not is_pointer(nake_type): return type elif isinstance(nake_type, cpptypes.volatile_t) and \ @@ -168,13 +228,13 @@ def remove_pointer(type): def is_reference(type): """returns True, if type represents C++ reference type, False otherwise""" - nake_type = type_traits_utils.remove_alias(type) + nake_type = remove_alias(type) return isinstance(nake_type, cpptypes.reference_t) def is_array(type): """returns True, if type represents C++ array type, False otherwise""" - nake_type = type_traits_utils.remove_alias(type) + nake_type = remove_alias(type) nake_type = remove_reference(nake_type) nake_type = remove_cv(nake_type) return isinstance(nake_type, cpptypes.array_t) @@ -182,7 +242,7 @@ def is_array(type): def array_size(type): """returns array size""" - nake_type = type_traits_utils.remove_alias(type) + nake_type = remove_alias(type) nake_type = remove_reference(nake_type) nake_type = remove_cv(nake_type) assert isinstance(nake_type, cpptypes.array_t) @@ -192,7 +252,7 @@ def array_size(type): def array_item_type(type_): """returns array item type""" if is_array(type_): - type_ = type_traits_utils.remove_alias(type_) + type_ = remove_alias(type_) type_ = remove_cv(type_) return type_.base elif is_pointer(type_): @@ -208,7 +268,7 @@ def remove_reference(type): If type is not reference type, it will be returned as is. """ - nake_type = type_traits_utils.remove_alias(type) + nake_type = remove_alias(type) if not is_reference(nake_type): return type else: @@ -217,7 +277,7 @@ def remove_reference(type): def is_const(type): """returns True, if type represents C++ const type, False otherwise""" - nake_type = type_traits_utils.remove_alias(type) + nake_type = remove_alias(type) if isinstance(nake_type, cpptypes.const_t): return True elif isinstance(nake_type, cpptypes.volatile_t): @@ -233,7 +293,7 @@ def remove_const(type_): If type is not const type, it will be returned as is """ - nake_type = type_traits_utils.remove_alias(type_) + nake_type = remove_alias(type_) if not is_const(nake_type): return type_ else: @@ -267,7 +327,7 @@ def remove_declarated(type_): If `type_` is not :class:`declarated_t`, it will be returned as is """ - type_ = type_traits_utils.remove_alias(type_) + type_ = remove_alias(type_) if isinstance(type_, cpptypes.declarated_t): type_ = type_.declaration return type_ @@ -282,7 +342,7 @@ def is_same(type1, type2): def is_volatile(type): """returns True, if type represents C++ volatile type, False otherwise""" - nake_type = type_traits_utils.remove_alias(type) + nake_type = remove_alias(type) if isinstance(nake_type, cpptypes.volatile_t): return True elif isinstance(nake_type, cpptypes.const_t): @@ -297,7 +357,7 @@ def remove_volatile(type): If type is not volatile type, it will be returned as is """ - nake_type = type_traits_utils.remove_alias(type) + nake_type = remove_alias(type) if not is_volatile(nake_type): return type else: @@ -317,7 +377,7 @@ def remove_volatile(type): def remove_cv(type): """removes const and volatile from the type definition""" - nake_type = type_traits_utils.remove_alias(type) + nake_type = remove_alias(type) if not is_const(nake_type) and not is_volatile(nake_type): return type result = nake_type @@ -404,7 +464,7 @@ def is_std_string(type_): if utils.is_str(type_): return type_ in string_equivalences else: - type_ = type_traits_utils.remove_alias(type_) + type_ = remove_alias(type_) return remove_cv(type_).decl_string in string_equivalences @@ -417,7 +477,7 @@ def is_std_wstring(type_): if utils.is_str(type_): return type_ in wstring_equivalences else: - type_ = type_traits_utils.remove_alias(type_) + type_ = remove_alias(type_) return remove_cv(type_).decl_string in wstring_equivalences @@ -430,7 +490,7 @@ def is_std_ostream(type_): if utils.is_str(type_): return type_ in ostream_equivalences else: - type_ = type_traits_utils.remove_alias(type_) + type_ = remove_alias(type_) return remove_cv(type_).decl_string in ostream_equivalences @@ -443,5 +503,5 @@ def is_std_wostream(type_): if utils.is_str(type_): return type_ in wostream_equivalences else: - type_ = type_traits_utils.remove_alias(type_) + type_ = remove_alias(type_) return remove_cv(type_).decl_string in wostream_equivalences diff --git a/pygccxml/declarations/type_traits_classes.py b/pygccxml/declarations/type_traits_classes.py index c868f17e..f868c956 100644 --- a/pygccxml/declarations/type_traits_classes.py +++ b/pygccxml/declarations/type_traits_classes.py @@ -7,7 +7,6 @@ from . import class_declaration from . import type_traits -from . import type_traits_utils from . import enumeration from . import calldef_members from . import calldef_types @@ -33,7 +32,7 @@ class declaration_xxx_traits(object): - get reference to the declaration """ sequence = [ - type_traits_utils.remove_alias, + type_traits.remove_alias, type_traits.remove_cv, type_traits.remove_declarated] @@ -299,13 +298,13 @@ def __find_class_by_class_declaration(self, class_decl): return found def __normalize(self, type_): - type_ = type_traits_utils.remove_alias(type_) - bt_of_type = type_traits_utils.base_type(type_) + type_ = type_traits.remove_alias(type_) + bt_of_type = type_traits.base_type(type_) if isinstance(bt_of_type, cpptypes.declarated_t) \ and isinstance(bt_of_type.declaration, class_declaration.class_declaration_t): type_ = type_.clone() - bt_of_type = type_traits_utils.base_type(type_) + bt_of_type = type_traits.base_type(type_) bt_of_type.declaration = self.__find_class_by_class_declaration( bt_of_type.declaration) return type_ @@ -342,13 +341,13 @@ def __test_trivial(self, source, target): type_traits.is_array(source) and \ type_traits.is_pointer(target): if type_traits.is_same( - type_traits_utils.base_type(source), target.base): + type_traits.base_type(source), target.base): return True # X[2] => X* if type_traits.is_array(source) and \ type_traits.is_pointer(target) and \ type_traits.is_const(target.base): if type_traits.is_same( - type_traits_utils.base_type(source), target.base.base): + type_traits.base_type(source), target.base.base): return True def __test_pointer_to_func_or_mv__to__func_or_mv(self, source, target): @@ -447,12 +446,12 @@ def __test_ref_x__to__y(self, source, target): def __test_fundamental__to__fundamental(self, source, target): if not type_traits.is_fundamental( - type_traits_utils.base_type(source)) or not \ + type_traits.base_type(source)) or not \ type_traits.is_fundamental( - type_traits_utils.base_type(target)): + type_traits.base_type(target)): return False - if type_traits.is_void(type_traits_utils.base_type(source)) or \ - type_traits.is_void(type_traits_utils.base_type(target)): + if type_traits.is_void(type_traits.base_type(source)) or \ + type_traits.is_void(type_traits.base_type(target)): return False if type_traits.is_fundamental(source) and \ type_traits.is_fundamental(target): @@ -477,8 +476,8 @@ def _is_both_declarated(self, x, y): isinstance(y, cpptypes.declarated_t)) def __test_derived_to_based(self, source, target): - derived = type_traits_utils.base_type(source) - base = type_traits_utils.base_type(target) + derived = type_traits.base_type(source) + base = type_traits.base_type(target) if not ( isinstance(derived, cpptypes.declarated_t) and isinstance(derived.declaration, class_declaration.class_t)): @@ -807,7 +806,7 @@ def is_copy_constructor(constructor): if not type_traits.is_const(arg.decl_type.base): return False - un_aliased = type_traits_utils.remove_alias(arg.decl_type.base) + un_aliased = type_traits.remove_alias(arg.decl_type.base) # un_aliased now refers to const_t instance if not isinstance(un_aliased.base, cpptypes.declarated_t): # We are looking for a declaration diff --git a/pygccxml/declarations/type_traits_utils.py b/pygccxml/declarations/type_traits_utils.py deleted file mode 100644 index 49ba5018..00000000 --- a/pygccxml/declarations/type_traits_utils.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2014-2016 Insight Software Consortium. -# Copyright 2004-2008 Roman Yakovenko. -# Distributed under the Boost Software License, Version 1.0. -# See http://www.boost.org/LICENSE_1_0.txt - -from . import typedef -from . import cpptypes - - -def __remove_alias(type_): - """implementation details""" - if isinstance(type_, typedef.typedef_t): - return __remove_alias(type_.decl_type) - if isinstance(type_, cpptypes.declarated_t) and \ - isinstance(type_.declaration, typedef.typedef_t): - return __remove_alias(type_.declaration.decl_type) - if isinstance(type_, cpptypes.compound_t): - type_.base = __remove_alias(type_.base) - return type_ - return type_ - - -def remove_alias(type_): - """returns type without typedefs""" - type_ref = None - if isinstance(type_, cpptypes.type_t): - type_ref = type_ - elif isinstance(type_, typedef.typedef_t): - type_ref = type_.decl_type - else: - pass # not a valid input, just return it - if not type_ref: - return type_ - if type_ref.cache.remove_alias: - return type_ref.cache.remove_alias - no_alias = __remove_alias(type_ref.clone()) - type_ref.cache.remove_alias = no_alias - return no_alias - - -def decompose_type(tp): - """implementation details""" - # implementation of this function is important - if isinstance(tp, cpptypes.compound_t): - return [tp] + decompose_type(tp.base) - elif isinstance(tp, typedef.typedef_t): - return decompose_type(tp.decl_type) - elif isinstance(tp, cpptypes.declarated_t) and \ - isinstance(tp.declaration, typedef.typedef_t): - return decompose_type(tp.declaration.decl_type) - else: - return [tp] - - -def decompose_class(type): - """implementation details""" - types = decompose_type(type) - return [tp.__class__ for tp in types] - - -def base_type(type): - """returns base type. - - For `const int` will return `int` - """ - types = decompose_type(type) - return types[-1] diff --git a/pygccxml/parser/patcher.py b/pygccxml/parser/patcher.py index b491e5ae..3c46601b 100644 --- a/pygccxml/parser/patcher.py +++ b/pygccxml/parser/patcher.py @@ -6,7 +6,7 @@ import re from .. import utils from .. import declarations -from ..declarations import type_traits_utils +from ..declarations import type_traits class default_argument_patcher_t(object): @@ -186,7 +186,7 @@ def __is_constructor_call(self, func, arg): if not call_invocation.is_call_invocation(dv): return False name = call_invocation.name(dv) - base_type = type_traits_utils.base_type(arg.decl_type) + base_type = type_traits.base_type(arg.decl_type) if not isinstance(base_type, declarations.declarated_t): return False decl = base_type.declaration @@ -200,7 +200,7 @@ def __fix_constructor_call(self, func, arg): dv = arg.default_value if not call_invocation.is_call_invocation(dv): return False - base_type = type_traits_utils.base_type(arg.decl_type) + base_type = type_traits.base_type(arg.decl_type) decl = base_type.declaration name, args = call_invocation.split(dv) if decl.name != name: From 6578671c6d458f6a96635dab565a0d65112e612c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 13 Jun 2016 21:04:04 +0200 Subject: [PATCH 176/268] Deprecate the container_traits attribute This fixes a cyclic import The find_container_traits from the declarations module should be used instead. The cachig mechanisme was preserved --- pygccxml/declarations/class_declaration.py | 28 ++++++++++++++++++---- pygccxml/declarations/container_traits.py | 20 ++++++++++++++++ unittests/find_container_traits_tester.py | 4 ++-- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 411475f9..108ecb3d 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -145,8 +145,9 @@ def __init__(self, name=''): ( and not definition )""" declaration.declaration_t.__init__(self, name) self._aliases = [] - self._container_traits = None - self._container_traits_set = False + self._container_traits = None # Deprecated + self._container_traits_set = False # Deprecated + self._container_traits_cache = None def _get__cmp__items(self): """implementation details""" @@ -167,11 +168,20 @@ def aliases(self, new_aliases): @property def container_traits(self): """reference to :class:`container_traits_impl_t` or None""" + + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The container_traits attribute is deprecated. \n" + + "Please use the find_container_traits function from the" + "declarations module instead.", + DeprecationWarning) + if self._container_traits_set is False: from . import container_traits # prevent cyclic dependencies self._container_traits_set = True self._container_traits = container_traits.find_container_traits( self) + self._container_traits_cache = self._container_traits return self._container_traits def _get_partial_name_impl(self): @@ -204,8 +214,9 @@ def __init__( self._aliases = [] self._byte_size = 0 self._byte_align = 0 - self._container_traits = None - self._container_traits_set = False + self._container_traits_cache = None + self._container_traits = None # Deprecated + self._container_traits_set = False # Deprecated self._recursive_bases = None self._recursive_derived = None self._use_demangled_as_name = False @@ -544,11 +555,20 @@ def i_depend_on_them(self, recursive=True): @property def container_traits(self): """reference to :class:`container_traits_impl_t` or None""" + + # Deprecated since 1.8.0. Will be removed in 1.9.0 + warnings.warn( + "The container_traits attribute is deprecated. \n" + + "Please use the find_container_traits function from the" + "declarations module instead.", + DeprecationWarning) + if self._container_traits_set is False: from . import container_traits # prevent cyclic dependencies self._container_traits_set = True self._container_traits = container_traits.find_container_traits( self) + self._container_traits_cache = self.container_traits return self._container_traits def find_copy_constructor(self): diff --git a/pygccxml/declarations/container_traits.py b/pygccxml/declarations/container_traits.py index 079f1ad5..05050864 100644 --- a/pygccxml/declarations/container_traits.py +++ b/pygccxml/declarations/container_traits.py @@ -688,6 +688,16 @@ def remove_defaults(self, type_or_string): def find_container_traits(cls_or_string): + """ + Find the container traits type of a declaration. + + Args: + cls_or_string (str | declarations.declaration_t): a string + + Returns: + declarations.container_traits: a container traits + """ + if utils.is_str(cls_or_string): if not templates.is_instantiation(cls_or_string): return None @@ -700,8 +710,18 @@ def find_container_traits(cls_or_string): if cls_traits.name() == name: return cls_traits else: + + if isinstance(cls_or_string, class_declaration.class_types): + # Look in the cache. + if cls_or_string._container_traits_cache is not None: + return cls_or_string._container_traits_cache + + # Look for a container traits for cls_traits in container_traits: if cls_traits.is_my_case(cls_or_string): + # Store in the cache + if isinstance(cls_or_string, class_declaration.class_types): + cls_or_string._container_traits_cache = cls_traits return cls_traits diff --git a/unittests/find_container_traits_tester.py b/unittests/find_container_traits_tester.py index 9cad6cdb..d3bca771 100644 --- a/unittests/find_container_traits_tester.py +++ b/unittests/find_container_traits_tester.py @@ -38,7 +38,7 @@ def __cmp_traits(self, typedef, expected, partial_name, key_type=None): expected.name(), traits.name())) cls = declarations.remove_declarated(typedef) - self.assertTrue(cls.container_traits is expected) + self.assertTrue(declarations.find_container_traits(cls) is expected) self.assertTrue(cls.partial_name == partial_name) cls = traits.class_declaration(cls) @@ -157,7 +157,7 @@ def test_remove_defaults_partial_name_namespace(self): f2 = self.global_ns.free_fun('f2') type_info = f2.return_type traits = declarations.find_container_traits(type_info) - cls = traits .class_declaration(type_info) + cls = traits.class_declaration(type_info) # traits.remove_defaults(type_info) decl_string = cls.partial_decl_string key_type_string = traits.key_type(type_info).partial_decl_string From 88ebd5d46403efe53a66f53e8c25514deaea670f Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 15 Jun 2016 23:55:50 +0200 Subject: [PATCH 177/268] Extract some more traits methods to a separate module The auto_ptr_traits, smart_pointer_traits and internal_type_traits are only imported in the __init__.py file, so they can easily be moved to a separate module (called other_traits). This reduces the number of imports in container_traits. The impl_details class is also moved to a separate module. --- pygccxml/declarations/__init__.py | 6 +- pygccxml/declarations/container_traits.py | 174 +------------------ pygccxml/declarations/other_traits.py | 105 +++++++++++ pygccxml/declarations/traits_impl_details.py | 86 +++++++++ 4 files changed, 197 insertions(+), 174 deletions(-) create mode 100644 pygccxml/declarations/other_traits.py create mode 100644 pygccxml/declarations/traits_impl_details.py diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 885378ff..0b6c3db9 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -184,9 +184,9 @@ from .type_traits_classes import find_noncopyable_vars from .type_traits_classes import has_any_non_copyconstructor -from .container_traits import auto_ptr_traits -from .container_traits import smart_pointer_traits -from .container_traits import internal_type_traits +from .other_traits import auto_ptr_traits +from .other_traits import smart_pointer_traits +from .other_traits import internal_type_traits from .container_traits import list_traits from .container_traits import deque_traits diff --git a/pygccxml/declarations/container_traits.py b/pygccxml/declarations/container_traits.py index 05050864..211dc611 100644 --- a/pygccxml/declarations/container_traits.py +++ b/pygccxml/declarations/container_traits.py @@ -14,8 +14,7 @@ from . import type_traits from . import namespace from . import class_declaration -from . import calldef -from . import class_declaration_traits +from . import traits_impl_details from .. import utils std_namespaces = ('std', 'stdext', '__gnu_cxx') @@ -422,7 +421,7 @@ def get_container_or_none(self, type_): decl = cls_declaration.parent for ns in std_namespaces: - if impl_details.is_defined_in_xxx(ns, decl): + if traits_impl_details.impl_details.is_defined_in_xxx(ns, decl): utils.loggers.queries_engine.debug( "Container traits: get_container_or_none() will return " + cls_declaration.name) @@ -482,7 +481,7 @@ def __find_xxx_type( result = type_traits.remove_declarated(xxx_type) else: xxx_type_str = templates.args(cls_declaration.name)[xxx_index] - result = impl_details.find_value_type( + result = traits_impl_details.impl_details.find_value_type( cls_declaration.top_parent, xxx_type_str) if None is result: raise RuntimeError( @@ -723,170 +722,3 @@ def find_container_traits(cls_or_string): if isinstance(cls_or_string, class_declaration.class_types): cls_or_string._container_traits_cache = cls_traits return cls_traits - - -class impl_details(object): - - """implementation details""" - @staticmethod - def is_defined_in_xxx(xxx, cls): - """implementation details""" - if not cls.parent: - return False - - if not isinstance(cls.parent, namespace.namespace_t): - return False - - if xxx != cls.parent.name: - return False - - xxx_ns = cls.parent - if not xxx_ns.parent: - return False - - if not isinstance(xxx_ns.parent, namespace.namespace_t): - return False - - if '::' != xxx_ns.parent.name: - return False - - global_ns = xxx_ns.parent - return None is global_ns.parent - - @staticmethod - def find_value_type(global_ns, value_type_str): - """implementation details""" - if not value_type_str.startswith('::'): - value_type_str = '::' + value_type_str - found = global_ns.decls( - name=value_type_str, - function=lambda decl: not isinstance(decl, calldef.calldef_t), - allow_empty=True) - if not found: - no_global_ns_value_type_str = value_type_str[2:] - if no_global_ns_value_type_str in cpptypes.FUNDAMENTAL_TYPES: - return cpptypes.FUNDAMENTAL_TYPES[no_global_ns_value_type_str] - elif type_traits.is_std_string(value_type_str): - string_ = global_ns.typedef('::std::string') - return type_traits.remove_declarated(string_) - elif type_traits.is_std_wstring(value_type_str): - string_ = global_ns.typedef('::std::wstring') - return type_traits.remove_declarated(string_) - else: - value_type_str = no_global_ns_value_type_str - has_const = value_type_str.startswith('const ') - if has_const: - value_type_str = value_type_str[len('const '):] - has_pointer = value_type_str.endswith('*') - if has_pointer: - value_type_str = value_type_str[:-1] - found = None - if has_const or has_pointer: - found = impl_details.find_value_type( - global_ns, - value_type_str) - if not found: - return None - else: - if isinstance(found, class_declaration.class_types): - found = cpptypes.declarated_t(found) - if has_const: - found = cpptypes.const_t(found) - if has_pointer: - found = cpptypes.pointer_t(found) - return found - if len(found) == 1: - return found[0] - else: - return None - - -class internal_type_traits(object): - - """small convenience class, which provides access to internal types""" - # TODO: add exists function - @staticmethod - def get_by_name(type_, name): - if class_declaration_traits.class_traits.is_my_case(type_): - cls = class_declaration_traits.class_traits.declaration_class( - type_) - return type_traits.remove_declarated( - cls.typedef(name, recursive=False).decl_type) - elif class_declaration_traits.is_my_case(type_): - cls = class_declaration_traits.get_declaration(type_) - value_type_str = templates.args(cls.name)[0] - ref = impl_details.find_value_type(cls.top_parent, value_type_str) - if ref: - return ref - else: - raise RuntimeError(( - "Unable to find reference to internal " + - "type '%s' in type '%s'.") % (name, cls.decl_string)) - else: - raise RuntimeError(( - "Unable to find reference to internal type '%s' in type '%s'.") - % (name, type_.decl_string)) - - -class smart_pointer_traits(object): - - """implements functionality, needed for convenient work with - smart pointers""" - - @staticmethod - def is_smart_pointer(type_): - """returns True, if type represents instantiation of - `boost::shared_ptr` or `std::shared_ptr`, False otherwise""" - type_ = type_traits.remove_alias(type_) - type_ = type_traits.remove_cv(type_) - type_ = type_traits.remove_declarated(type_) - if not isinstance(type_, - (class_declaration.class_declaration_t, - class_declaration.class_t)): - return False - if not (impl_details.is_defined_in_xxx('boost', type_) or - impl_details.is_defined_in_xxx('std', type_)): - return False - return type_.decl_string.startswith('::boost::shared_ptr<') or \ - type_.decl_string.startswith('::std::shared_ptr<') - - @staticmethod - def value_type(type_): - """returns reference to `boost::shared_ptr` \ - or `std::shared_ptr` value type""" - if not smart_pointer_traits.is_smart_pointer(type_): - raise TypeError( - 'Type "%s" is not an instantiation of \ - boost::shared_ptr or std::shared_ptr' % - type_.decl_string) - return internal_type_traits.get_by_name(type_, "value_type") - - -class auto_ptr_traits(object): - - """implements functionality, needed for convenient work with - `std::auto_ptr` pointers""" - - @staticmethod - def is_smart_pointer(type_): - """returns True, if type represents instantiation of - `boost::shared_ptr`, False otherwise""" - type_ = type_traits.remove_alias(type_) - type_ = type_traits.remove_cv(type_) - type_ = type_traits.remove_declarated(type_) - if not isinstance(type_, - (class_declaration.class_declaration_t, - class_declaration.class_t)): - return False - if not impl_details.is_defined_in_xxx('std', type_): - return False - return type_.decl_string.startswith('::std::auto_ptr<') - - @staticmethod - def value_type(type_): - """returns reference to `boost::shared_ptr` value type""" - if not auto_ptr_traits.is_smart_pointer(type_): - raise TypeError( - 'Type "%s" is not instantiation of std::auto_ptr' % - type_.decl_string) - return internal_type_traits.get_by_name(type_, "element_type") diff --git a/pygccxml/declarations/other_traits.py b/pygccxml/declarations/other_traits.py new file mode 100644 index 00000000..9a19041f --- /dev/null +++ b/pygccxml/declarations/other_traits.py @@ -0,0 +1,105 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +from . import templates +from . import type_traits +from . import class_declaration +from . import class_declaration_traits +from . import traits_impl_details + + +class internal_type_traits(object): + + """small convenience class, which provides access to internal types""" + # TODO: add exists function + @staticmethod + def get_by_name(type_, name): + if class_declaration_traits.class_traits.is_my_case(type_): + cls = class_declaration_traits.class_traits.declaration_class( + type_) + return type_traits.remove_declarated( + cls.typedef(name, recursive=False).decl_type) + elif class_declaration_traits.is_my_case(type_): + cls = class_declaration_traits.get_declaration(type_) + value_type_str = templates.args(cls.name)[0] + ref = traits_impl_details.impl_details.find_value_type( + cls.top_parent, value_type_str) + if ref: + return ref + else: + raise RuntimeError(( + "Unable to find reference to internal " + + "type '%s' in type '%s'.") % (name, cls.decl_string)) + else: + raise RuntimeError(( + "Unable to find reference to internal type '%s' in type '%s'.") + % (name, type_.decl_string)) + + +class smart_pointer_traits(object): + + """implements functionality, needed for convenient work with + smart pointers""" + + @staticmethod + def is_smart_pointer(type_): + """returns True, if type represents instantiation of + `boost::shared_ptr` or `std::shared_ptr`, False otherwise""" + type_ = type_traits.remove_alias(type_) + type_ = type_traits.remove_cv(type_) + type_ = type_traits.remove_declarated(type_) + if not isinstance(type_, + (class_declaration.class_declaration_t, + class_declaration.class_t)): + return False + if not (traits_impl_details.impl_details.is_defined_in_xxx( + 'boost', type_) or + traits_impl_details.impl_details.is_defined_in_xxx( + 'std', type_)): + return False + return type_.decl_string.startswith('::boost::shared_ptr<') or \ + type_.decl_string.startswith('::std::shared_ptr<') + + @staticmethod + def value_type(type_): + """returns reference to `boost::shared_ptr` \ + or `std::shared_ptr` value type""" + if not smart_pointer_traits.is_smart_pointer(type_): + raise TypeError( + 'Type "%s" is not an instantiation of \ + boost::shared_ptr or std::shared_ptr' % + type_.decl_string) + return internal_type_traits.get_by_name(type_, "value_type") + + +class auto_ptr_traits(object): + + """implements functionality, needed for convenient work with + `std::auto_ptr` pointers""" + + @staticmethod + def is_smart_pointer(type_): + """returns True, if type represents instantiation of + `boost::shared_ptr`, False otherwise""" + type_ = type_traits.remove_alias(type_) + type_ = type_traits.remove_cv(type_) + type_ = type_traits.remove_declarated(type_) + if not isinstance(type_, + (class_declaration.class_declaration_t, + class_declaration.class_t)): + return False + if not traits_impl_details.impl_details.is_defined_in_xxx( + 'std', type_): + return False + return type_.decl_string.startswith('::std::auto_ptr<') + + @staticmethod + def value_type(type_): + """returns reference to `boost::shared_ptr` value type""" + if not auto_ptr_traits.is_smart_pointer(type_): + raise TypeError( + 'Type "%s" is not instantiation of std::auto_ptr' % + type_.decl_string) + return internal_type_traits.get_by_name(type_, "element_type") diff --git a/pygccxml/declarations/traits_impl_details.py b/pygccxml/declarations/traits_impl_details.py new file mode 100644 index 00000000..b9961657 --- /dev/null +++ b/pygccxml/declarations/traits_impl_details.py @@ -0,0 +1,86 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +from . import namespace +from . import calldef +from . import cpptypes +from . import type_traits +from . import class_declaration + + +class impl_details(object): + + """implementation details""" + @staticmethod + def is_defined_in_xxx(xxx, cls): + """implementation details""" + if not cls.parent: + return False + + if not isinstance(cls.parent, namespace.namespace_t): + return False + + if xxx != cls.parent.name: + return False + + xxx_ns = cls.parent + if not xxx_ns.parent: + return False + + if not isinstance(xxx_ns.parent, namespace.namespace_t): + return False + + if '::' != xxx_ns.parent.name: + return False + + global_ns = xxx_ns.parent + return None is global_ns.parent + + @staticmethod + def find_value_type(global_ns, value_type_str): + """implementation details""" + if not value_type_str.startswith('::'): + value_type_str = '::' + value_type_str + found = global_ns.decls( + name=value_type_str, + function=lambda decl: not isinstance(decl, calldef.calldef_t), + allow_empty=True) + if not found: + no_global_ns_value_type_str = value_type_str[2:] + if no_global_ns_value_type_str in cpptypes.FUNDAMENTAL_TYPES: + return cpptypes.FUNDAMENTAL_TYPES[no_global_ns_value_type_str] + elif type_traits.is_std_string(value_type_str): + string_ = global_ns.typedef('::std::string') + return type_traits.remove_declarated(string_) + elif type_traits.is_std_wstring(value_type_str): + string_ = global_ns.typedef('::std::wstring') + return type_traits.remove_declarated(string_) + else: + value_type_str = no_global_ns_value_type_str + has_const = value_type_str.startswith('const ') + if has_const: + value_type_str = value_type_str[len('const '):] + has_pointer = value_type_str.endswith('*') + if has_pointer: + value_type_str = value_type_str[:-1] + found = None + if has_const or has_pointer: + found = impl_details.find_value_type( + global_ns, + value_type_str) + if not found: + return None + else: + if isinstance(found, class_declaration.class_types): + found = cpptypes.declarated_t(found) + if has_const: + found = cpptypes.const_t(found) + if has_pointer: + found = cpptypes.pointer_t(found) + return found + if len(found) == 1: + return found[0] + else: + return None From 968890f6967643dbd3dcfbe3814d060a76c29fe7 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 20 Jun 2016 22:27:29 +0200 Subject: [PATCH 178/268] Add missing has_vtable import --- pygccxml/declarations/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 0b6c3db9..050c2923 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -183,6 +183,7 @@ from .type_traits_classes import find_copy_constructor from .type_traits_classes import find_noncopyable_vars from .type_traits_classes import has_any_non_copyconstructor +from .type_traits_classes import has_vtable from .other_traits import auto_ptr_traits from .other_traits import smart_pointer_traits From c4bdc00612ce9e92be74c3942c4f7d9d5dbef9da Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 20 Jun 2016 22:27:52 +0200 Subject: [PATCH 179/268] Document future deprecations --- CHANGELOG.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f183af02..493be524 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,9 +20,23 @@ Version 1.8.0 (not yet released) * Documentation update and cleanup -* Remove compiler attribute in declarations.py and gccxml_path from config.py +* [Removals] Remove compiler attribute in declarations.py and gccxml_path from config.py These were deprecated in pygccxml v1.7.0, and definitively removed for v1.8.0 +* [Deprecations] A bunch of attributes and methods were deprecated. + They will throw a warning when used with pygccxml 1.8.0, and will be removed + in version 1.9.0. + * In ``class_declaration_t``` and ```class_t```: + - decl.container_traits attribute => declarations.find_container_traits(decl) + * In ```class_t``` + - decl.find_noncopyable_vars() method => declarations.find_noncopyable_vars(decl) + - decl.find_copy_constructor() method => declarations.find_copy_constructor(decl) + - decl.has_vtable argument => declarations.has_vtable(decl) + * ```constructor_t``` + - ctor.is_copy_constructor attribute => declarations.is_copy_constructor(ctor) + - ctor.is_trivial_constructor attribute => declarations.is_trivial_constructor(ctor) + + Version 1.7.6 ------------- From 00ec7b077e82291354ec99260f4af80a4b5b5f70 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 20 Jun 2016 22:52:14 +0200 Subject: [PATCH 180/268] Fix unexpected parameter names in docstrings --- pygccxml/declarations/call_invocation.py | 2 +- pygccxml/parser/source_reader.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pygccxml/declarations/call_invocation.py b/pygccxml/declarations/call_invocation.py index b0c37483..b5b550e5 100644 --- a/pygccxml/declarations/call_invocation.py +++ b/pygccxml/declarations/call_invocation.py @@ -56,7 +56,7 @@ def args(declaration_string): """ Returns list of function arguments - :type decl_string: str + :type declaration_string: str :rtype: [str] """ diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 97a038c8..c16bcbd9 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -21,7 +21,6 @@ def bind_aliases(decls): This function binds between class and it's typedefs. :param decls: list of all declarations - :type all_classes: list of :class:`declarations.declaration_t` items :rtype: None From e579c2425375b9b7afc19dadbbeb3fa6773b7874 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 20 Jun 2016 23:17:17 +0200 Subject: [PATCH 181/268] Cleanup declarations setters/getters in namespace and scopedef classes The implementation was messing up the type checking of pycharm. Docstrings were added --- pygccxml/declarations/namespace.py | 18 ++++++++++++++---- pygccxml/declarations/scopedef.py | 20 +++++++++++++++++++- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/pygccxml/declarations/namespace.py b/pygccxml/declarations/namespace.py index 43c394f9..bd42831c 100644 --- a/pygccxml/declarations/namespace.py +++ b/pygccxml/declarations/namespace.py @@ -48,15 +48,25 @@ def _get__cmp__scope_items(self): def _get_declarations_impl(self): return self._declarations - @scopedef.scopedef_t.declarations.setter - def declarations(self, declarations): + @property + def declarations(self): """ - List of all declarations defined in the namespace. + List of children declarations. - The getter is defined in scopedef.scopedef_t. + Returns: + List[declarations.declaration_t] + """ + return scopedef.scopedef_t.declarations.fget(self) + @declarations.setter + def declarations(self, declarations): """ + Set list of all declarations defined in the namespace. + Args: + List[declarations.declaration_t]: list of declarations + + """ self._declarations = declarations def take_parenting(self, inst): diff --git a/pygccxml/declarations/scopedef.py b/pygccxml/declarations/scopedef.py index 336a263c..05627bf3 100644 --- a/pygccxml/declarations/scopedef.py +++ b/pygccxml/declarations/scopedef.py @@ -236,12 +236,30 @@ def _get_declarations_impl(self): @property def declarations(self): - """list of children :class:`declarations `""" + """ + List of children declarations. + + Returns: + List[declarations.declaration_t] + """ if self._optimized: return self._all_decls_not_recursive else: return self._get_declarations_impl() + @declarations.setter + def declarations(self, declarations): + """ + Set list of all declarations defined in the namespace. + + Args: + List[declarations.declaration_t]: list of declarations + + Not implemented. + + """ + raise NotImplementedError() + def remove_declaration(self, decl): raise NotImplementedError() From 8920b5464ebbb7043f3f01814d8dc0722cae82f1 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 22 Jun 2016 10:27:46 +0200 Subject: [PATCH 182/268] Make declarations.is_string and friends work with references See #15 --- CHANGELOG.md | 6 ++++++ pygccxml/declarations/type_traits.py | 16 ++++++++++++---- unittests/data/string_traits.hpp | 10 ++++++++-- unittests/data/type_traits.hpp | 8 ++++++-- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 493be524..42036bb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ Version 1.8.0 (not yet released) is the one used since many years now. The two other classes will be removed in 1.9.0. +* ```declarations.is_string```, ```declarations.is_std_wstring```, + ```declarations.is_std_ostream``` and ```declarations.is_std_wostream``` now + correctly work when a the type is also a reference. + Example: ```declarations.is_string``` returned false for + ```typedef std::string& x3;```; it will return true now. + * General code style overhaul (with the help of quantifiedcode.com) * Added a bunch of new examples diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index f174c436..c811f2fe 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -465,7 +465,9 @@ def is_std_string(type_): return type_ in string_equivalences else: type_ = remove_alias(type_) - return remove_cv(type_).decl_string in string_equivalences + type_ = remove_reference(type_) + type_ = remove_cv(type_) + return type_.decl_string in string_equivalences def is_std_wstring(type_): @@ -478,7 +480,9 @@ def is_std_wstring(type_): return type_ in wstring_equivalences else: type_ = remove_alias(type_) - return remove_cv(type_).decl_string in wstring_equivalences + type_ = remove_reference(type_) + type_ = remove_cv(type_) + return type_.decl_string in wstring_equivalences def is_std_ostream(type_): @@ -491,7 +495,9 @@ def is_std_ostream(type_): return type_ in ostream_equivalences else: type_ = remove_alias(type_) - return remove_cv(type_).decl_string in ostream_equivalences + type_ = remove_reference(type_) + type_ = remove_cv(type_) + return type_.decl_string in ostream_equivalences def is_std_wostream(type_): @@ -504,4 +510,6 @@ def is_std_wostream(type_): return type_ in wostream_equivalences else: type_ = remove_alias(type_) - return remove_cv(type_).decl_string in wostream_equivalences + type_ = remove_reference(type_) + type_ = remove_cv(type_) + return type_.decl_string in wostream_equivalences diff --git a/unittests/data/string_traits.hpp b/unittests/data/string_traits.hpp index 25e8d6d3..3a5a4ee9 100644 --- a/unittests/data/string_traits.hpp +++ b/unittests/data/string_traits.hpp @@ -9,11 +9,14 @@ namespace string_traits{ namespace yes{ typedef std::string x1; typedef const std::string x2; + typedef std::string& x3; + typedef const std::string& x4; } namespace no{ typedef int x1; - typedef std::string& x2; + typedef const int x2; + typedef const int& x3; } } @@ -22,11 +25,14 @@ namespace wstring_traits{ namespace yes{ typedef std::wstring x1; typedef const std::wstring x2; + typedef std::wstring& x3; + typedef const std::wstring& x4; } namespace no{ typedef int x1; - typedef std::wstring& x2; + typedef const int x2; + typedef const int& x3; } } diff --git a/unittests/data/type_traits.hpp b/unittests/data/type_traits.hpp index 08254ee8..b46d8642 100644 --- a/unittests/data/type_traits.hpp +++ b/unittests/data/type_traits.hpp @@ -27,7 +27,9 @@ struct some_struct_t{ namespace is_std_ostream{ namespace yes{ - typedef std::ostream ostream_type; + typedef std::ostream ostream_type1; + typedef std::ostream& ostream_type2; + typedef const std::ostream& ostream_type3; } namespace no{ typedef int int__; @@ -36,7 +38,9 @@ namespace no{ namespace is_std_wostream{ namespace yes{ - typedef std::wostream wostream_type; + typedef std::wostream wostream_type1; + typedef std::wostream& wostream_type2; + typedef const std::wostream& wostream_type3; } namespace no{ typedef int int__; From df69dafff1dbed8c68d66fadd377eb31fee0587f Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 22 Jun 2016 10:36:47 +0200 Subject: [PATCH 183/268] Rename variable, do not override type --- pygccxml/declarations/type_traits.py | 92 ++++++++++++++-------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index c811f2fe..2faa8b1c 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -69,18 +69,18 @@ def decompose_type(tp): return [tp] -def decompose_class(type): +def decompose_class(type_): """implementation details""" - types = decompose_type(type) + types = decompose_type(type_) return [tp.__class__ for tp in types] -def base_type(type): +def base_type(type_): """returns base type. For `const int` will return `int` """ - types = decompose_type(type) + types = decompose_type(type_) return types[-1] @@ -129,18 +129,18 @@ def is_bool(type_): cpptypes.bool_t()) -def is_void(type): +def is_void(type_): """returns True, if type represents `void`, False otherwise""" - return remove_alias(type) in create_cv_types( + return remove_alias(type_) in create_cv_types( cpptypes.void_t()) -def is_void_pointer(type): +def is_void_pointer(type_): """returns True, if type represents `void*`, False otherwise""" - return is_same(type, cpptypes.pointer_t(cpptypes.void_t())) + return is_same(type_, cpptypes.pointer_t(cpptypes.void_t())) -def is_integral(type): +def is_integral(type_): """returns True, if type represents C++ integral type, False otherwise""" integral_def = ( create_cv_types(cpptypes.char_t()) + @@ -159,10 +159,10 @@ def is_integral(type): create_cv_types(cpptypes.int128_t()) + create_cv_types(cpptypes.uint128_t())) - return remove_alias(type) in integral_def + return remove_alias(type_) in integral_def -def is_floating_point(type): +def is_floating_point(type_): """returns True, if type represents C++ floating point type, False otherwise""" float_def = ( @@ -170,44 +170,44 @@ def is_floating_point(type): create_cv_types(cpptypes.double_t()) + create_cv_types(cpptypes.long_double_t())) - return remove_alias(type) in float_def + return remove_alias(type_) in float_def -def is_arithmetic(type): +def is_arithmetic(type_): """returns True, if type represents C++ integral or floating point type, False otherwise""" - return is_integral(type) or is_floating_point(type) + return is_integral(type_) or is_floating_point(type_) -def is_pointer(type): +def is_pointer(type_): """returns True, if type represents C++ pointer type, False otherwise""" - return does_match_definition(type, + return does_match_definition(type_, cpptypes.pointer_t, (cpptypes.const_t, cpptypes.volatile_t)) \ - or does_match_definition(type, + or does_match_definition(type_, cpptypes.pointer_t, (cpptypes.volatile_t, cpptypes.const_t)) -def is_calldef_pointer(type): +def is_calldef_pointer(type_): """returns True, if type represents pointer to free/member function, False otherwise""" - if not is_pointer(type): + if not is_pointer(type_): return False - nake_type = remove_alias(type) + nake_type = remove_alias(type_) nake_type = remove_cv(nake_type) return isinstance(nake_type, cpptypes.compound_t) \ and isinstance(nake_type.base, cpptypes.calldef_type_t) -def remove_pointer(type): +def remove_pointer(type_): """removes pointer from the type definition If type is not pointer type, it will be returned as is. """ - nake_type = remove_alias(type) + nake_type = remove_alias(type_) if not is_pointer(nake_type): - return type + return type_ elif isinstance(nake_type, cpptypes.volatile_t) and \ isinstance(nake_type.base, cpptypes.pointer_t): return cpptypes.volatile_t(nake_type.base.base) @@ -221,28 +221,28 @@ def remove_pointer(type): cpptypes.volatile_t(cpptypes.const_t(nake_type.base.base.base)) ) elif isinstance(nake_type.base, cpptypes.calldef_type_t): - return type + return type_ else: return nake_type.base -def is_reference(type): +def is_reference(type_): """returns True, if type represents C++ reference type, False otherwise""" - nake_type = remove_alias(type) + nake_type = remove_alias(type_) return isinstance(nake_type, cpptypes.reference_t) -def is_array(type): +def is_array(type_): """returns True, if type represents C++ array type, False otherwise""" - nake_type = remove_alias(type) + nake_type = remove_alias(type_) nake_type = remove_reference(nake_type) nake_type = remove_cv(nake_type) return isinstance(nake_type, cpptypes.array_t) -def array_size(type): +def array_size(type_): """returns array size""" - nake_type = remove_alias(type) + nake_type = remove_alias(type_) nake_type = remove_reference(nake_type) nake_type = remove_cv(nake_type) assert isinstance(nake_type, cpptypes.array_t) @@ -263,21 +263,21 @@ def array_item_type(type_): "types") -def remove_reference(type): +def remove_reference(type_): """removes reference from the type definition If type is not reference type, it will be returned as is. """ - nake_type = remove_alias(type) + nake_type = remove_alias(type_) if not is_reference(nake_type): - return type + return type_ else: return nake_type.base -def is_const(type): +def is_const(type_): """returns True, if type represents C++ const type, False otherwise""" - nake_type = remove_alias(type) + nake_type = remove_alias(type_) if isinstance(nake_type, cpptypes.const_t): return True elif isinstance(nake_type, cpptypes.volatile_t): @@ -340,9 +340,9 @@ def is_same(type1, type2): return nake_type1 == nake_type2 -def is_volatile(type): +def is_volatile(type_): """returns True, if type represents C++ volatile type, False otherwise""" - nake_type = remove_alias(type) + nake_type = remove_alias(type_) if isinstance(nake_type, cpptypes.volatile_t): return True elif isinstance(nake_type, cpptypes.const_t): @@ -352,14 +352,14 @@ def is_volatile(type): return False -def remove_volatile(type): +def remove_volatile(type_): """removes volatile from the type definition If type is not volatile type, it will be returned as is """ - nake_type = remove_alias(type) + nake_type = remove_alias(type_) if not is_volatile(nake_type): - return type + return type_ else: if isinstance(nake_type, cpptypes.array_t): is_c = is_const(nake_type) @@ -374,12 +374,12 @@ def remove_volatile(type): return nake_type.base -def remove_cv(type): +def remove_cv(type_): """removes const and volatile from the type definition""" - nake_type = remove_alias(type) + nake_type = remove_alias(type_) if not is_const(nake_type) and not is_volatile(nake_type): - return type + return type_ result = nake_type if is_const(result): result = remove_const(result) @@ -390,14 +390,14 @@ def remove_cv(type): return result -def is_fundamental(type): +def is_fundamental(type_): """returns True, if type represents C++ fundamental type""" return does_match_definition( - type, + type_, cpptypes.fundamental_t, (cpptypes.const_t, cpptypes.volatile_t)) \ or does_match_definition( - type, + type_, cpptypes.fundamental_t, (cpptypes.volatile_t, cpptypes.const_t)) From 033fb68cdf60e4b7001d8eb005dfb960c9db8e16 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 22 Jun 2016 10:50:30 +0200 Subject: [PATCH 184/268] Update changelog --- CHANGELOG.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42036bb9..2b00304c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,14 +6,6 @@ Version 1.8.0 (not yet released) * find_xml_generator will now look for castxml first -* Deprecate the ns() method. The namespace() method can be used instead. - ns() will be removed in 1.9.0. - -* Deprecate etree_scanner_t and etree_saxifier_t classes. - The most efficient xml scanner class is the ietree_scanner_t class, which - is the one used since many years now. The two other classes will be removed - in 1.9.0. - * ```declarations.is_string```, ```declarations.is_std_wstring```, ```declarations.is_std_ostream``` and ```declarations.is_std_wostream``` now correctly work when a the type is also a reference. @@ -42,6 +34,12 @@ Version 1.8.0 (not yet released) - ctor.is_copy_constructor attribute => declarations.is_copy_constructor(ctor) - ctor.is_trivial_constructor attribute => declarations.is_trivial_constructor(ctor) + * Deprecate the ns() method. The namespace() method can be used instead. + + * Deprecate etree_scanner_t and etree_saxifier_t classes. + The most efficient xml scanner class is the ietree_scanner_t class, which + is the one used since many years now. + Version 1.7.6 ------------- From e5ab26077fb3048725b2cf558a81317861ccfee3 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 22 Jun 2016 11:35:59 +0200 Subject: [PATCH 185/268] Add example on how to work with function arguments Also, demonstrate the usage of is_std_string and is_reference (see #15) --- docs/examples.rst | 1 + docs/examples/functions/example.hpp | 12 ++++++++ docs/examples/functions/example.py | 45 +++++++++++++++++++++++++++++ docs/examples/functions/example.rst | 18 ++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 docs/examples/functions/example.hpp create mode 100644 docs/examples/functions/example.py create mode 100644 docs/examples/functions/example.rst diff --git a/docs/examples.rst b/docs/examples.rst index 5fad9692..9c951ae2 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -14,5 +14,6 @@ First examples examples/searching1/example.rst examples/searching/example.rst examples/equality/example.rst + examples/functions/example.rst examples/caching/example.rst examples/print-example/example.rst diff --git a/docs/examples/functions/example.hpp b/docs/examples/functions/example.hpp new file mode 100644 index 00000000..ca579fc9 --- /dev/null +++ b/docs/examples/functions/example.hpp @@ -0,0 +1,12 @@ +// Copyright 2014-2016 Insight Software Consortium. +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +#include +using namespace std; + +namespace ns{ + int myFunction(int a, const std::string& x1) { + return a + 1; + } +} diff --git a/docs/examples/functions/example.py b/docs/examples/functions/example.py new file mode 100644 index 00000000..bad9e9dd --- /dev/null +++ b/docs/examples/functions/example.py @@ -0,0 +1,45 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +from pygccxml import utils +from pygccxml import declarations +from pygccxml import parser + +import os +import sys +import warnings +warnings.simplefilter("error", Warning) +# Find out the file location within the sources tree +this_module_dir_path = os.path.abspath( + os.path.dirname(sys.modules[__name__].__file__)) + +# Find out the c++ parser +generator_path, generator_name = utils.find_xml_generator() + +# Configure the xml generator +xml_generator_config = parser.xml_generator_configuration_t( + xml_generator_path=generator_path, + xml_generator=generator_name) + +# The c++ file we want to parse +filename = "example.hpp" +filename = this_module_dir_path + "/" + filename + +decls = parser.parse([filename], xml_generator_config) +global_namespace = declarations.get_global_namespace(decls) +ns = global_namespace.namespace("ns") + +# Use the free_functions method to find our function +func = ns.free_function(name="myFunction") + +# There are two arguments: +print(len(func.arguments)) + +# We can loop over them and print some information: +for arg in func.arguments: + print( + arg.name, + str(arg.decl_type), + declarations.is_std_string(arg.decl_type), + declarations.is_reference(arg.decl_type)) diff --git a/docs/examples/functions/example.rst b/docs/examples/functions/example.rst new file mode 100644 index 00000000..06d906b0 --- /dev/null +++ b/docs/examples/functions/example.rst @@ -0,0 +1,18 @@ +======================= +Functions and arguments +======================= + +This example shows how to work with function arguments + +Let's consider the following c++ file: + +.. literalinclude:: example.hpp + :language: c++ + :lines: 4- + +The following code can be used to find the different arguments of a function and +do some basic operations on them: + +.. literalinclude:: example.py + :language: python + :lines: 5,6,7,16-26,28- From 74bd8e3348a389d5420dac2b965c79ab46460590 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 22 Jun 2016 16:24:53 +0200 Subject: [PATCH 186/268] Enable the reopen cache test This was previously forgotten so that the test was not being run. --- unittests/test_all.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/unittests/test_all.py b/unittests/test_all.py index be0620df..fd790eab 100644 --- a/unittests/test_all.py +++ b/unittests/test_all.py @@ -72,6 +72,7 @@ import unnamed_classes_tester import test_map_gcc5 import test_argument_without_name +import reopen_cache_tester testers = [ # , demangled_tester # failing right now @@ -136,7 +137,8 @@ test_cpp_standards, unnamed_classes_tester, test_map_gcc5, - test_argument_without_name + test_argument_without_name, + reopen_cache_tester ] if 'posix' in os.name: From ff4fca18f28fd18bf0fb92bfe5e899cd01680599 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 22 Jun 2016 17:03:58 +0200 Subject: [PATCH 187/268] Revert "Enable the reopen cache test" This reverts commit 74bd8e3348a389d5420dac2b965c79ab46460590. This is already tested by the file_cache_tester. I was confused by the fact that the content of the test was not appearing in the code coverage. I will need to investigate this later. --- unittests/test_all.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/unittests/test_all.py b/unittests/test_all.py index fd790eab..be0620df 100644 --- a/unittests/test_all.py +++ b/unittests/test_all.py @@ -72,7 +72,6 @@ import unnamed_classes_tester import test_map_gcc5 import test_argument_without_name -import reopen_cache_tester testers = [ # , demangled_tester # failing right now @@ -137,8 +136,7 @@ test_cpp_standards, unnamed_classes_tester, test_map_gcc5, - test_argument_without_name, - reopen_cache_tester + test_argument_without_name ] if 'posix' in os.name: From f215edb3649e726c9a1de74cc2f1a4018842a4d4 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 22 Jun 2016 21:58:57 +0200 Subject: [PATCH 188/268] Improve installation instructions (#31) --- docs/install.rst | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/docs/install.rst b/docs/install.rst index 0a47758a..fe2f0ade 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -4,7 +4,14 @@ Download & Install Prerequisite: CastXML --------------------- -You need to have `CastXML`_ installed. +`CastXML`_ needs to be installed on your system. + +1) If you are on linux or mac, your package manager may already provide a "castxml" package. + +2) You can download pre-compiled binaries for `Linux`_, for `OS X`_ and for `Windows`_. + +3) You can compile CastXML from source, either with the `SuperBuild`_, or by following the `full install instructions`_ . + Installation of pygccxml ------------------------ @@ -20,19 +27,23 @@ To install from source, you can use the usual procedure: GCC-XML (Legacy) ---------------- -These instructions are only here for historical reasons; `pygccxml` is now using -`CastXML` by default. +These instructions are only here for historical reasons. `GCC-XML`_ was the tool used +to generate the xml files before CastXML existed. -There are few different ways to install `GCC-XML`_ on your system: +**From version v1.8.0 on, pygccxml uses CastXML by default. +The support for GCC-XML will finally be dropped in pygccxml v2.0.0.** -1. If you use Linux, than I am almost sure your system provides the "gccxml" package. - Consider to install it using "native"(rpm, deb, portage) packaging system. +There are few different ways to install GCC-XML on your system: -.. line separator +1) Most Linux system provide the "gccxml" package through their package manager. -2. Another option is to install it from the source code. See the `instructions`_ here. - Installation from sources supported for Windows, Linux and Mac platforms. +2) See the `instructions`_ to install GCC-XML from source. -.. _`instructions` : http://gccxml.org/HTML/Install.html +.. _`instructions`: http://gccxml.org/HTML/Install.html .. _`GCC-XML`: http://www.gccxml.org .. _`CastXML`: https://github.com/CastXML/CastXML +.. _`Linux`: https://midas3.kitware.com/midas/download/bitstream/460535/castxml-linux.tar.gz +.. _`OS X`: https://midas3.kitware.com/midas/download/bitstream/460536/castxml-macosx.tar.gz +.. _`Windows`: https://midas3.kitware.com/midas/download/bitstream/460537/castxml-windows.zip +.. _`SuperBuild`: https://github.com/thewtex/CastXMLSuperbuild +.. _`full install instructions`: https://github.com/CastXML/CastXML#build From b33c815376052723de2bdbf22d8380394f54af55 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 22 Jun 2016 22:09:08 +0200 Subject: [PATCH 189/268] Fix code coverage path for the examples --- .coveragerc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.coveragerc b/.coveragerc index 4e650856..1ea4f40b 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,5 +1,5 @@ [run] -source = pygccxml,docs/example,unittests +source = pygccxml,docs/examples,unittests # unittest/misc contains some tests that are just there for debugging # purposes and which do not need to be covered. omit = unittests/misc From 7fa4bb0dc66c18098abad83e8b201b001701007c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 22 Jun 2016 22:25:23 +0200 Subject: [PATCH 190/268] Enable code coverage for reopen_cache_tester.py file --- unittests/file_cache_tester.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/unittests/file_cache_tester.py b/unittests/file_cache_tester.py index aff69dd7..99c01012 100644 --- a/unittests/file_cache_tester.py +++ b/unittests/file_cache_tester.py @@ -85,9 +85,20 @@ def test_reopen_cache(self): Test opening cache files in a subprocess (with a clean environment). """ + + env = os.environ.copy() + + # Get the path to current directory + path = os.path.dirname(os.path.realpath(__file__)) + # Set the COVERAGE_PROCESS_START env. variable. + # Allows to cover files run in a subprocess + # http://nedbatchelder.com/code/coverage/subprocess.html + env["COVERAGE_PROCESS_START"] = path + "/../.coveragerc" + p = subprocess.Popen( [sys.executable, "unittests/reopen_cache_tester.py"], - stdout=subprocess.PIPE) + stdout=subprocess.PIPE, + env=env) print(p.stdout.read()) p.stdout.close() From 9c0d0c953407f51cf3076b50a839a900f850ce30 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 16:47:59 +0200 Subject: [PATCH 191/268] Update the readme (#31) --- README.rst | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/README.rst b/README.rst index 4d3955e9..5a00eb98 100644 --- a/README.rst +++ b/README.rst @@ -19,25 +19,19 @@ pygccxml is a specialized XML reader that reads the output from CastXML or GCCXM Install ------- -You can use pip to install pygccxml: +Install instructions can be found `here `_. - pip install pygccxml +Documentation and examples +-------------------------- -To install from source, you can use the usual procedure: - - python setup.py install +The documentation can be found `here `_, examples can be found `here `_. Contact us ---------- -You can contact us through the CastXML mailing list: http://public.kitware.com/mailman/listinfo/castxml - -For issues with pygccxml you can open an issue here: https://github.com/gccxml/pygccxml/issues - -Documentation -------------- +You can contact us through the `CastXML mailing list `_. -For examples and tutorials see the documentation: http://pygccxml.readthedocs.io +For issues with pygccxml you can open an issue `here `_. Branches -------- @@ -50,8 +44,6 @@ Testing and code coverage ------------------------- pygccxml has more than 200 unit tests. They are run after each code commit to ensure -that the code stays functional and stable. You can find the builds here: -https://travis-ci.org/gccxml/pygccxml/builds +that the code stays functional and stable. You can find the builds `here `_. -Code coverage is also available. It is automatically updated after each commit and can be found here: -https://coveralls.io/r/gccxml/pygccxml +Code coverage is also available. It is automatically updated after each commit and can be found `here `_. From 8263bf8e983ed604259bd987dc32be686b9b4212 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 17:39:31 +0200 Subject: [PATCH 192/268] Add more detailled information on how to build the docs --- docs/documentation.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/documentation.rst b/docs/documentation.rst index 726c40a9..2fd9fd45 100644 --- a/docs/documentation.rst +++ b/docs/documentation.rst @@ -5,12 +5,17 @@ Building the documentation locally ---------------------------------- You can build the documentation yourself. In order for this to work you need -sphinx doc (http://sphinx-doc.org). Then just run the following command -in the root folder: +sphinx doc (http://sphinx-doc.org) and the readthedocs theme: + + pip install sphinx + + pip install sphinx_rtd_theme + +Then just run the following command in the root folder: make html -This will build the documentation locally in the docs/_build/html folder. +This will build the documentation locally in the `docs/_build/html` folder. For each commit on the master and develop branches, the documentation is automatically built and can be found here: https://readthedocs.org/projects/pygccxml/ From feb7d36471f0b20c40d95acd4d10900abb1234f4 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 17:53:02 +0200 Subject: [PATCH 193/268] Improve the documenation of load_xml_generator_configuration Instead of providing a separate example configuration file, link to the one in the unittests (they have already drifted apart, I will update the one in the unnittests in the next commit) --- pygccxml/parser/config.py | 53 +++++++++++++-------------------------- 1 file changed, 18 insertions(+), 35 deletions(-) diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index 86381ac2..215cad04 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -321,43 +321,26 @@ def raise_on_wrong_settings(self): def load_xml_generator_configuration(configuration, **defaults): """ - loads CastXML or GCC-XML configuration from an `.ini` file or any other - file class - :class:`configparser.ConfigParser` is able to parse. - - :param configuration: configuration could be - string(configuration file path) or instance - of :class:`configparser.ConfigParser` class - - :rtype: :class:`.xml_generator_configuration_t` - - Configuration file skeleton:: - - [gccxml] - #path to gccxml or castxml executable file - optional, if not provided, - os.environ['PATH'] - #variable is used to find it - gccxml_path=(deprecated) - xml_generator_path= - #gccxml working directory - optional, could be set to your source - code directory - working_directory= - #additional include directories, separated by ';' - include_paths= - #gccxml has a nice algorithms, which selects what C++ compiler - to emulate. - #You can explicitly set what compiler it should emulate. - #Valid options are: g++, msvc6, msvc7, msvc71, msvc8, cl. - compiler= - # gccxml or castxml - xml_generator= - # Do we keep xml files or not after errors - keep_xml= - # Set the path to the compiler - compiler_path= + Loads CastXML or GCC-XML configuration. + + Args: + configuration (string|configparser.ConfigParser): can be + a string (file path to a configuration file) or + instance of :class:`configparser.ConfigParser`. + defaults: can be used to override single configuration values. + + Returns: + :class:`.xml_generator_configuration_t`: a configuration object - """ + The file passed needs to be in a format that can be parsed by + :class:`configparser.ConfigParser`. + + An example configuration file skeleton can be found + `here `_. + + """ parser = configuration if utils.is_str(configuration): try: From f409411aca3cf635dd61f7ff8e2a65cccffb39a1 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 17:59:04 +0200 Subject: [PATCH 194/268] Update the documentation of the default xml configuration file (#31) --- unittests/xml_generator.cfg | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/unittests/xml_generator.cfg b/unittests/xml_generator.cfg index 25666a04..b1290c1c 100644 --- a/unittests/xml_generator.cfg +++ b/unittests/xml_generator.cfg @@ -1,14 +1,17 @@ [gccxml] -#path to castxml or gccxml executable file - optional, if not provided, os.environ['PATH'] -#variable is used to find it +# Specify which xml generator you want to use "castxml" or "gccxml" +# "castxml is the default" +xml_generator= +# Path to castxml or gccxml executable file xml_generator_path= -#gccxml working directory - optional, could be set to your source code directory +# Set the path to the compiler (for example "/usr/bin/gcc") for CastXML +compiler_path= +# Gccxml working directory - optional, could be set to your source code directory working_directory= -#additional include directories, separated by ';' or ':' +# Additional include directories, as list of paths ["path1/file1.h", "path2/file2.h", ...] include_paths= -#gccxml has a nice algorithms, which selects what C++ compiler to emulate. -#You can explicitly set what compiler it should emulate. -#Valid options are: g++, msvc6, msvc7, msvc71, msvc8, cl. +# You can explicitly set what compiler it should emulate (for GCCXML) +# Valid options are: g++, msvc6, msvc7, msvc71, msvc8, cl. compiler= -# gccxml or castxml -xml_generator= +# Keep xml files after errors (useful for debugging) +keep_xml= From 78dc137ba4b17d6a90f2c373488998e1e8ef8018 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 17:59:59 +0200 Subject: [PATCH 195/268] Import on top --- pygccxml/parser/config.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index 215cad04..39ae2851 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -12,6 +12,10 @@ import copy import platform import subprocess +try: + from configparser import ConfigParser +except ImportError: + from ConfigParser import SafeConfigParser as ConfigParser from .. import utils @@ -343,10 +347,6 @@ def load_xml_generator_configuration(configuration, **defaults): """ parser = configuration if utils.is_str(configuration): - try: - from configparser import ConfigParser - except ImportError: - from ConfigParser import SafeConfigParser as ConfigParser parser = ConfigParser() parser.read(configuration) From 1064e1b69f7eeed77de50250702f5d3a5634dee4 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 18:40:10 +0200 Subject: [PATCH 196/268] Add deprecation warnings for gccxml_configuration_t and load_gccxml_configuration --- pygccxml/parser/config.py | 15 ++++++++++++--- pygccxml/utils/utils.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index 39ae2851..f09d7f2f 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -424,9 +424,18 @@ def create_compiler_path(xml_generator, compiler_path): return compiler_path -# Keep these for backward compatibility -gccxml_configuration_t = xml_generator_configuration_t -load_gccxml_configuration = load_xml_generator_configuration + +gccxml_configuration_t = utils.utils.DeprecationWrapper( + xml_generator_configuration_t, + "gccxml_configuration_t", + "xml_generator_configuration_t", + "1.9.0") +load_gccxml_configuration = utils.utils.DeprecationWrapper( + load_xml_generator_configuration, + "load_gccxml_configuration", + "load_xml_generator_configuration", + "1.9.0") + if __name__ == '__main__': print(load_xml_generator_configuration('xml_generator.cfg').__dict__) diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index a0792d24..ee57ce73 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -469,3 +469,31 @@ def is_cxx14_or_greater(self): def is_cxx1z(self): """Returns true if -std=c++1z is being used""" return self._cplusplus == cxx_standard.__STD_CXX['-std=c++1z'] + + +class DeprecationWrapper(object): + """ + A small wrapper class useful when deprecation classes. + + This class is not part of the public API. + + """ + def __init__(self, new_target, old_name, new_name, version): + self.new_target = new_target + self.old_name = old_name + self.new_name = new_name + self.version = version + + def _warn(self): + warnings.warn( + self.old_name + " is deprecated. Please use " + self.new_name + + " instead. This will be removed in version " + self.version, + DeprecationWarning) + + def __call__(self, *args, **kwargs): + self._warn() + return self.new_target(*args, **kwargs) + + def __getattr__(self, attr): + self._warn() + return getattr(self.new_target, attr) From 879fd41d4a6a5406b2baea458fe3ec077b94b4ee Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 19:11:53 +0200 Subject: [PATCH 197/268] Deprecate gccxml_configuration_example We do not want multiple examples which will drift apart. The only example file that is provided is in the unittests folder. --- pygccxml/parser/config.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index f09d7f2f..e0b9d736 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -12,6 +12,7 @@ import copy import platform import subprocess +import warnings try: from configparser import ConfigParser except ImportError: @@ -298,7 +299,29 @@ def raise_on_wrong_settings(self): 'valid file name.') % self.xml_generator_path raise RuntimeError(msg) -gccxml_configuration_example = \ + +class _StringDeprecationWrapper(str): + """ + A small wrapper class useful when deprecation strings. + + This class is not part of the public API. + + """ + + def __new__(cls, content): + cls.content = content + return str.__new__(cls, content) + + def __str__(self): + warnings.warn( + "gccxml_configuration_example is deprecated. There is an " + + "example file here if you need one: unittests/xml_generator.cfg" + "This will be removed in version 1.9.0", + DeprecationWarning) + return self.content + + +gccxml_configuration_example = _StringDeprecationWrapper( """ [gccxml] #path to gccxml executable file - optional, if not provided, os.environ['PATH'] @@ -320,7 +343,7 @@ def raise_on_wrong_settings(self): keep_xml= # Set the path to the compiler compiler_path= -""" +""") def load_xml_generator_configuration(configuration, **defaults): From e9cda1814f69d414bb188727dd9c40a4b595accd Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 19:23:57 +0200 Subject: [PATCH 198/268] The [gccxml] section used in the configuration file is now deprecated Please use [xml_generator] instead. --- CHANGELOG.md | 3 +++ pygccxml/parser/config.py | 9 +++++++++ unittests/xml_generator.cfg | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b00304c..b5160379 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,9 @@ Version 1.8.0 (not yet released) * Deprecate etree_scanner_t and etree_saxifier_t classes. The most efficient xml scanner class is the ietree_scanner_t class, which is the one used since many years now. + + * The [gccxml] section used in the configuration file is now deprecated. + Please use [xml_generator] instead. Version 1.7.6 diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index e0b9d736..ee29ec9b 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -381,10 +381,19 @@ def load_xml_generator_configuration(configuration, **defaults): values = {} if parser.has_section('gccxml'): + warnings.warn( + "The [gccxml] section in your configuration file is deprecated. " + "Please use [xml_generator] instead. This will no more work with " + "version 1.9.0") for name, value in parser.items('gccxml'): if value.strip(): values[name] = value + if parser.has_section('xml_generator'): + for name, value in parser.items('xml_generator'): + if value.strip(): + values[name] = value + for name, value in values.items(): if isinstance(value, str): value = value.strip() diff --git a/unittests/xml_generator.cfg b/unittests/xml_generator.cfg index b1290c1c..cb00818e 100644 --- a/unittests/xml_generator.cfg +++ b/unittests/xml_generator.cfg @@ -1,4 +1,4 @@ -[gccxml] +[xml_generator] # Specify which xml generator you want to use "castxml" or "gccxml" # "castxml is the default" xml_generator= From 8b730cd68231fff5466b704980d5a61399260399 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 22:24:05 +0200 Subject: [PATCH 199/268] Increase code coverage for find_noncopyable_vars method (#16) --- unittests/data/non_copyable_classes.hpp | 17 +++++++++++++++++ unittests/non_copyable_classes_tester.py | 3 +++ 2 files changed, 20 insertions(+) diff --git a/unittests/data/non_copyable_classes.hpp b/unittests/data/non_copyable_classes.hpp index aaa0501c..1d3dafef 100644 --- a/unittests/data/non_copyable_classes.hpp +++ b/unittests/data/non_copyable_classes.hpp @@ -89,6 +89,23 @@ class MainFoo4 : Foo4 { char b; }; +// ----------------------------------------------- + +// Foo5 is a base class, with a variable foo of type Foo4, which is not +// copyable +class Foo5 { + private: + Foo5(); + protected: + const Foo4 foo; +}; + +// Use the base class +class MainFoo5 : Foo5 { + public: + char b; +}; + } #endif//__non_copyable_classes_hpp__ diff --git a/unittests/non_copyable_classes_tester.py b/unittests/non_copyable_classes_tester.py index c8c52d91..690386e7 100644 --- a/unittests/non_copyable_classes_tester.py +++ b/unittests/non_copyable_classes_tester.py @@ -49,6 +49,9 @@ def test(self): MainFoo4 = self.global_ns.class_('MainFoo4') self.assertTrue(declarations.is_noncopyable(MainFoo4)) + MainFoo5 = self.global_ns.class_('MainFoo5') + self.assertTrue(declarations.is_noncopyable(MainFoo5)) + def create_suite(): suite = unittest.TestSuite() From b44664fef315f7a67bcfe19ada63a0db5119e8a2 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 22:37:12 +0200 Subject: [PATCH 200/268] Use more pythonic variable names, update documentation --- unittests/non_copyable_classes_tester.py | 30 ++++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/unittests/non_copyable_classes_tester.py b/unittests/non_copyable_classes_tester.py index 690386e7..3bb8f807 100644 --- a/unittests/non_copyable_classes_tester.py +++ b/unittests/non_copyable_classes_tester.py @@ -25,32 +25,32 @@ def setUp(self): def test(self): """ - Search for two classes which can not be copied. + Search for classes which can not be copied. See bug #13 - Covers two cases for the moment 1) non copyable class - 2) non copyable const (fundamental type) - 3) non copyable const (class type) - 4) non copyable const (array type) + 2) non copyable const variable (fundamental type) + 3) non copyable const variable (class type) + 4) non copyable const variable (array type) + 5) non copyable const variable (class type) """ - MainFoo1 = self.global_ns.class_('MainFoo1') - self.assertTrue(declarations.is_noncopyable(MainFoo1)) + main_foo_1 = self.global_ns.class_('MainFoo1') + self.assertTrue(declarations.is_noncopyable(main_foo_1)) - MainFoo2 = self.global_ns.class_('MainFoo2') - self.assertTrue(declarations.is_noncopyable(MainFoo2)) + main_foo_2 = self.global_ns.class_('MainFoo2') + self.assertTrue(declarations.is_noncopyable(main_foo_2)) - MainFoo3 = self.global_ns.class_('MainFoo3') - self.assertTrue(declarations.is_noncopyable(MainFoo3)) + main_foo_3 = self.global_ns.class_('MainFoo3') + self.assertTrue(declarations.is_noncopyable(main_foo_3)) - MainFoo4 = self.global_ns.class_('MainFoo4') - self.assertTrue(declarations.is_noncopyable(MainFoo4)) + main_foo_4 = self.global_ns.class_('MainFoo4') + self.assertTrue(declarations.is_noncopyable(main_foo_4)) - MainFoo5 = self.global_ns.class_('MainFoo5') - self.assertTrue(declarations.is_noncopyable(MainFoo5)) + main_foo_5 = self.global_ns.class_('MainFoo5') + self.assertTrue(declarations.is_noncopyable(main_foo_5)) def create_suite(): From 0961bf55c3b5c63b13179e896e876eae95e73f86 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 22:44:40 +0200 Subject: [PATCH 201/268] Rename test classes, use more pythonic name --- unittests/array_bug_tester.py | 4 ++-- unittests/attributes_tester.py | 10 +++++----- unittests/better_templates_matcher_tester.py | 10 +++++----- unittests/bit_fields_tester.py | 10 +++++----- unittests/bsc_tester.py | 4 ++-- unittests/cached_source_file_tester.py | 4 ++-- unittests/calldef_matcher_tester.py | 4 ++-- unittests/calling_convention_tester.py | 4 ++-- unittests/complex_types_tester.py | 4 ++-- unittests/const_volatile_arg_tester.py | 12 ++++++------ unittests/copy_constructor_tester.py | 4 ++-- unittests/decl_printer_tester.py | 4 ++-- unittests/decl_string_tester.py | 10 +++++----- unittests/declaration_files_tester.py | 4 ++-- unittests/declaration_matcher_tester.py | 12 ++++++------ unittests/declarations_comparison_tester.py | 4 ++-- unittests/dependencies_tester.py | 12 ++++++------ unittests/example_tester.py | 4 ++-- unittests/file_cache_tester.py | 4 ++-- unittests/filters_tester.py | 12 ++++++------ unittests/find_container_traits_tester.py | 10 +++++----- unittests/free_operators_tester.py | 4 ++-- unittests/from_future_import_tester.py | 4 ++-- unittests/function_traits_tester.py | 10 +++++----- unittests/gccxml10183_tester.py | 4 ++-- unittests/gccxml10184_tester.py | 4 ++-- unittests/gccxml10185_tester.py | 4 ++-- unittests/gccxml_runner_tester.py | 4 ++-- unittests/has_binary_operator_traits_tester.py | 10 +++++----- unittests/hierarchy_traveling.py | 4 ++-- unittests/inline_specifier_tester.py | 10 +++++----- unittests/namespace_matcher_tester.py | 4 ++-- unittests/non_copyable_classes_tester.py | 4 ++-- unittests/pep8_tester.py | 4 ++-- unittests/plain_c_tester.py | 4 ++-- unittests/project_reader_correctness_tester.py | 4 ++-- unittests/remove_template_defaults_tester.py | 10 +++++----- unittests/source_reader_tester.py | 12 ++++++------ unittests/start_with_declarations_tester.py | 4 ++-- unittests/string_traits_tester.py | 10 +++++----- unittests/templates_tester.py | 4 ++-- unittests/test_argument_without_name.py | 4 ++-- unittests/test_copy_constructor.py | 4 ++-- unittests/test_create_decl_string.py | 4 ++-- unittests/test_map_gcc5.py | 4 ++-- unittests/test_utils.py | 4 ++-- unittests/test_va_list_tag_removal.py | 4 ++-- unittests/text_reader_tester.py | 4 ++-- unittests/type_as_exception_bug_tester.py | 10 +++++----- unittests/type_traits_tester.py | 16 ++++++++-------- unittests/undname_creator_tester.py | 10 +++++----- unittests/unnamed_classes_tester.py | 4 ++-- unittests/vector_traits_tester.py | 10 +++++----- unittests/xmlfile_reader_tester.py | 4 ++-- 54 files changed, 173 insertions(+), 173 deletions(-) diff --git a/unittests/array_bug_tester.py b/unittests/array_bug_tester.py index eb2014ff..f43e6e95 100644 --- a/unittests/array_bug_tester.py +++ b/unittests/array_bug_tester.py @@ -10,7 +10,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -117,7 +117,7 @@ def test7(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/attributes_tester.py b/unittests/attributes_tester.py index 3ed81cb8..3a5f8f8c 100644 --- a/unittests/attributes_tester.py +++ b/unittests/attributes_tester.py @@ -11,7 +11,7 @@ from pygccxml import utils -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None def __init__(self, *args): @@ -21,10 +21,10 @@ def __init__(self, *args): self.header = "attributes_" + self.config.xml_generator + ".hpp" def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() def test(self): @@ -50,7 +50,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/better_templates_matcher_tester.py b/unittests/better_templates_matcher_tester.py index 7eed0ab7..67517e4b 100644 --- a/unittests/better_templates_matcher_tester.py +++ b/unittests/better_templates_matcher_tester.py @@ -10,7 +10,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None @@ -19,10 +19,10 @@ def __init__(self, *args): self.header = 'better_templates_matcher_tester.hpp' def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() def test(self): classes = [ @@ -36,7 +36,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/bit_fields_tester.py b/unittests/bit_fields_tester.py index b2c93a17..61baaf8a 100644 --- a/unittests/bit_fields_tester.py +++ b/unittests/bit_fields_tester.py @@ -10,7 +10,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None @@ -19,10 +19,10 @@ def __init__(self, *args): self.header = 'bit_fields.hpp' def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() def test(self): bf_x = self.global_ns.variable('x') @@ -40,7 +40,7 @@ def test2(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/bsc_tester.py b/unittests/bsc_tester.py index 7b1a6231..27c5a3e2 100644 --- a/unittests/bsc_tester.py +++ b/unittests/bsc_tester.py @@ -5,7 +5,7 @@ from pygccxml.binary_parsers import bsc -class tester_t(unittest.TestCase): +class Test(unittest.TestCase): def __init__(self, *args): unittest.TestCase.__init__(self, *args) @@ -32,7 +32,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/cached_source_file_tester.py b/unittests/cached_source_file_tester.py index 3539c8a3..9eaf631b 100644 --- a/unittests/cached_source_file_tester.py +++ b/unittests/cached_source_file_tester.py @@ -12,7 +12,7 @@ from pygccxml import parser -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -40,7 +40,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/calldef_matcher_tester.py b/unittests/calldef_matcher_tester.py index 85e17888..af8c00cf 100644 --- a/unittests/calldef_matcher_tester.py +++ b/unittests/calldef_matcher_tester.py @@ -9,7 +9,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE def __init__(self, *args): @@ -32,7 +32,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/calling_convention_tester.py b/unittests/calling_convention_tester.py index 7c7a071f..23881e8b 100644 --- a/unittests/calling_convention_tester.py +++ b/unittests/calling_convention_tester.py @@ -7,7 +7,7 @@ from pygccxml import declarations -class tester_t(unittest.TestCase): +class Test(unittest.TestCase): def test_extract(self): data = [ @@ -26,7 +26,7 @@ def test_extract(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/complex_types_tester.py b/unittests/complex_types_tester.py index 5327d794..76015c7c 100644 --- a/unittests/complex_types_tester.py +++ b/unittests/complex_types_tester.py @@ -9,7 +9,7 @@ from pygccxml import parser -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE def __init__(self, *args): @@ -32,7 +32,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() if os.name != 'nt': - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/const_volatile_arg_tester.py b/unittests/const_volatile_arg_tester.py index 6ec459ec..cb6c2971 100644 --- a/unittests/const_volatile_arg_tester.py +++ b/unittests/const_volatile_arg_tester.py @@ -9,7 +9,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None def __init__(self, *args): @@ -18,11 +18,11 @@ def __init__(self, *args): self.global_ns = None def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() - self.global_ns = tester_t.global_ns + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() + self.global_ns = Test.global_ns def test(self): f = self.global_ns.free_fun('pygccxml_bug') @@ -35,7 +35,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/copy_constructor_tester.py b/unittests/copy_constructor_tester.py index e22dd751..4b0cc2e7 100644 --- a/unittests/copy_constructor_tester.py +++ b/unittests/copy_constructor_tester.py @@ -12,7 +12,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -59,7 +59,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/decl_printer_tester.py b/unittests/decl_printer_tester.py index 2345b299..e24a36fe 100644 --- a/unittests/decl_printer_tester.py +++ b/unittests/decl_printer_tester.py @@ -11,7 +11,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -65,7 +65,7 @@ def test__str__(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/decl_string_tester.py b/unittests/decl_string_tester.py index f7509522..13615408 100644 --- a/unittests/decl_string_tester.py +++ b/unittests/decl_string_tester.py @@ -11,7 +11,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE global_ns = None @@ -27,10 +27,10 @@ def __init__(self, *args): """ def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() def test_member_function(self): member_inline_call = self.global_ns.mem_fun('member_inline_call') @@ -70,7 +70,7 @@ def test_all_mem_and_free_funs(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/declaration_files_tester.py b/unittests/declaration_files_tester.py index 4a0b87c5..c4fea6c2 100644 --- a/unittests/declaration_files_tester.py +++ b/unittests/declaration_files_tester.py @@ -10,7 +10,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -42,7 +42,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/declaration_matcher_tester.py b/unittests/declaration_matcher_tester.py index 818f0ec0..4f8ac2e8 100644 --- a/unittests/declaration_matcher_tester.py +++ b/unittests/declaration_matcher_tester.py @@ -10,7 +10,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE @@ -20,11 +20,11 @@ def __init__(self, *args): self.global_ns = None def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() - self.global_ns = tester_t.global_ns + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() + self.global_ns = Test.global_ns def test_global(self): gns = self.global_ns @@ -67,7 +67,7 @@ def test_ns1(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/declarations_comparison_tester.py b/unittests/declarations_comparison_tester.py index 7843578f..d181c82f 100644 --- a/unittests/declarations_comparison_tester.py +++ b/unittests/declarations_comparison_tester.py @@ -10,7 +10,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE def __init__(self, *args): @@ -72,7 +72,7 @@ def test_same_declarations_different_intances(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/dependencies_tester.py b/unittests/dependencies_tester.py index 020ec9fc..393b1827 100644 --- a/unittests/dependencies_tester.py +++ b/unittests/dependencies_tester.py @@ -11,7 +11,7 @@ from pygccxml import utils -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None def __init__(self, *args): @@ -20,11 +20,11 @@ def __init__(self, *args): self.global_ns = None def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() - self.global_ns = tester_t.global_ns + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() + self.global_ns = Test.global_ns def test_variable(self): ns_vars = self.global_ns.namespace('::declarations::variables') @@ -99,7 +99,7 @@ def test_coverage(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/example_tester.py b/unittests/example_tester.py index b5478810..51ce819d 100644 --- a/unittests/example_tester.py +++ b/unittests/example_tester.py @@ -8,7 +8,7 @@ import subprocess -class tester_t(unittest.TestCase): +class Test(unittest.TestCase): def test_example(self): """Runs the example in the docs directory""" @@ -39,7 +39,7 @@ def test_example(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/file_cache_tester.py b/unittests/file_cache_tester.py index 99c01012..1e592326 100644 --- a/unittests/file_cache_tester.py +++ b/unittests/file_cache_tester.py @@ -12,7 +12,7 @@ from pygccxml import parser -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE def __init__(self, *args): @@ -105,7 +105,7 @@ def test_reopen_cache(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/filters_tester.py b/unittests/filters_tester.py index 437136de..a18b4899 100644 --- a/unittests/filters_tester.py +++ b/unittests/filters_tester.py @@ -11,7 +11,7 @@ from pygccxml import utils -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE @@ -21,11 +21,11 @@ def __init__(self, *args): self.global_ns = None def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() - self.global_ns = tester_t.global_ns + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() + self.global_ns = Test.global_ns def test_regex(self): criteria = declarations.regex_matcher_t( @@ -94,7 +94,7 @@ def test_not_matcher(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/find_container_traits_tester.py b/unittests/find_container_traits_tester.py index d3bca771..bdff4b10 100644 --- a/unittests/find_container_traits_tester.py +++ b/unittests/find_container_traits_tester.py @@ -10,7 +10,7 @@ from pygccxml import utils -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None def __init__(self, *args): @@ -18,10 +18,10 @@ def __init__(self, *args): self.headers = ['remove_template_defaults.hpp', 'indexing_suites2.hpp'] def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse(self.headers, self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() def __cmp_traits(self, typedef, expected, partial_name, key_type=None): if utils.is_str(typedef): @@ -189,7 +189,7 @@ def test_infinite_loop(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/free_operators_tester.py b/unittests/free_operators_tester.py index 2531c753..ba1911c4 100644 --- a/unittests/free_operators_tester.py +++ b/unittests/free_operators_tester.py @@ -9,7 +9,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -34,7 +34,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/from_future_import_tester.py b/unittests/from_future_import_tester.py index 8db6ef3a..db2afb9d 100644 --- a/unittests/from_future_import_tester.py +++ b/unittests/from_future_import_tester.py @@ -11,7 +11,7 @@ from pygccxml import parser -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): """ Some methods like namespace() verify if their argument is a string. @@ -40,7 +40,7 @@ def setUp(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/function_traits_tester.py b/unittests/function_traits_tester.py index ed0aaef7..799f6b79 100644 --- a/unittests/function_traits_tester.py +++ b/unittests/function_traits_tester.py @@ -10,7 +10,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None @@ -19,10 +19,10 @@ def __init__(self, *args): self.header = 'covariant_returns.hpp' def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() def test_is_same_function(self): d = self.global_ns.class_('better_algorithm_t') @@ -37,7 +37,7 @@ def test_is_same_function(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/gccxml10183_tester.py b/unittests/gccxml10183_tester.py index 25a6c07f..065d08e8 100644 --- a/unittests/gccxml10183_tester.py +++ b/unittests/gccxml10183_tester.py @@ -17,7 +17,7 @@ """ -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -38,7 +38,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/gccxml10184_tester.py b/unittests/gccxml10184_tester.py index 75a657f9..60a4a5d6 100644 --- a/unittests/gccxml10184_tester.py +++ b/unittests/gccxml10184_tester.py @@ -19,7 +19,7 @@ class A { """ -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -34,7 +34,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/gccxml10185_tester.py b/unittests/gccxml10185_tester.py index e7e32391..37a0549c 100644 --- a/unittests/gccxml10185_tester.py +++ b/unittests/gccxml10185_tester.py @@ -18,7 +18,7 @@ """ -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -52,7 +52,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/gccxml_runner_tester.py b/unittests/gccxml_runner_tester.py index 4762414d..be159b36 100644 --- a/unittests/gccxml_runner_tester.py +++ b/unittests/gccxml_runner_tester.py @@ -9,7 +9,7 @@ from pygccxml import parser -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE def __init__(self, *args): @@ -26,7 +26,7 @@ def test_gccxml_on_input_with_errors(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/has_binary_operator_traits_tester.py b/unittests/has_binary_operator_traits_tester.py index 00178485..af68081a 100644 --- a/unittests/has_binary_operator_traits_tester.py +++ b/unittests/has_binary_operator_traits_tester.py @@ -10,7 +10,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE global_ns = None @@ -20,10 +20,10 @@ def __init__(self, *args): self.global_ns = None def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - self.global_ns = tester_t.global_ns + Test.global_ns = declarations.get_global_namespace(decls) + self.global_ns = Test.global_ns def test_yes(self): yes_ns = self.global_ns.namespace('yes') @@ -44,7 +44,7 @@ def test_no(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/hierarchy_traveling.py b/unittests/hierarchy_traveling.py index 7cdbb3c9..510791cd 100644 --- a/unittests/hierarchy_traveling.py +++ b/unittests/hierarchy_traveling.py @@ -11,7 +11,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -77,7 +77,7 @@ def test_recursive_derived(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/inline_specifier_tester.py b/unittests/inline_specifier_tester.py index 408e2b26..d50b65cc 100644 --- a/unittests/inline_specifier_tester.py +++ b/unittests/inline_specifier_tester.py @@ -9,7 +9,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None @@ -18,10 +18,10 @@ def __init__(self, *args): self.header = 'inline_specifier.hpp' def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() def test(self): inlined_funcs = self.global_ns.calldefs('inlined') @@ -40,7 +40,7 @@ def test2(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/namespace_matcher_tester.py b/unittests/namespace_matcher_tester.py index 8872a602..4eaf33ac 100644 --- a/unittests/namespace_matcher_tester.py +++ b/unittests/namespace_matcher_tester.py @@ -9,7 +9,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE def __init__(self, *args): @@ -53,7 +53,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) suite.addTest(unittest.makeSuite(unnamed_ns_tester_t)) return suite diff --git a/unittests/non_copyable_classes_tester.py b/unittests/non_copyable_classes_tester.py index 3bb8f807..01fba939 100644 --- a/unittests/non_copyable_classes_tester.py +++ b/unittests/non_copyable_classes_tester.py @@ -9,7 +9,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -55,7 +55,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/pep8_tester.py b/unittests/pep8_tester.py index 73685dd5..ab7b2101 100644 --- a/unittests/pep8_tester.py +++ b/unittests/pep8_tester.py @@ -5,7 +5,7 @@ import fnmatch -class tester_t(unittest.TestCase): +class Test(unittest.TestCase): def test_pep8_conformance_unitests(self): """Pep8 conformance test (unitests) @@ -83,7 +83,7 @@ def run_check(self, path): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/plain_c_tester.py b/unittests/plain_c_tester.py index 99e2aeb7..379ca794 100644 --- a/unittests/plain_c_tester.py +++ b/unittests/plain_c_tester.py @@ -9,7 +9,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -32,7 +32,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/project_reader_correctness_tester.py b/unittests/project_reader_correctness_tester.py index 6b5fed4f..7099ec51 100644 --- a/unittests/project_reader_correctness_tester.py +++ b/unittests/project_reader_correctness_tester.py @@ -12,7 +12,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -93,7 +93,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) suite.addTest(unittest.makeSuite(tester2_t)) return suite diff --git a/unittests/remove_template_defaults_tester.py b/unittests/remove_template_defaults_tester.py index 35165f08..3ff86008 100644 --- a/unittests/remove_template_defaults_tester.py +++ b/unittests/remove_template_defaults_tester.py @@ -10,7 +10,7 @@ from pygccxml import utils -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None def __init__(self, *args): @@ -18,10 +18,10 @@ def __init__(self, *args): self.header = 'remove_template_defaults.hpp' def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() def test_vector(self): v_int = self.global_ns.typedef('v_int') @@ -203,7 +203,7 @@ def test_hash_multimap(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/source_reader_tester.py b/unittests/source_reader_tester.py index 7f6247fa..a6bfeec2 100644 --- a/unittests/source_reader_tester.py +++ b/unittests/source_reader_tester.py @@ -10,7 +10,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None def __init__(self, *args): @@ -19,11 +19,11 @@ def __init__(self, *args): self.global_ns = None def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() - self.global_ns = tester_t.global_ns + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() + self.global_ns = Test.global_ns def test_compound_argument_type(self): do_smth = self.global_ns.calldefs('do_smth') @@ -33,7 +33,7 @@ def test_compound_argument_type(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/start_with_declarations_tester.py b/unittests/start_with_declarations_tester.py index 26430315..a789cca1 100644 --- a/unittests/start_with_declarations_tester.py +++ b/unittests/start_with_declarations_tester.py @@ -11,7 +11,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -54,7 +54,7 @@ def test_project_reader_all_at_once(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/string_traits_tester.py b/unittests/string_traits_tester.py index 7e74f9e8..5ed1395f 100644 --- a/unittests/string_traits_tester.py +++ b/unittests/string_traits_tester.py @@ -9,7 +9,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE global_ns = None @@ -19,10 +19,10 @@ def __init__(self, *args): self.global_ns = None def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - self.global_ns = tester_t.global_ns + Test.global_ns = declarations.get_global_namespace(decls) + self.global_ns = Test.global_ns def validate_yes(self, ns, controller): for typedef in ns.typedefs(): @@ -53,7 +53,7 @@ def test_wstring(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/templates_tester.py b/unittests/templates_tester.py index 4fca1e63..60fc9703 100644 --- a/unittests/templates_tester.py +++ b/unittests/templates_tester.py @@ -8,7 +8,7 @@ from pygccxml import declarations -class tester_t(unittest.TestCase): +class Test(unittest.TestCase): def __test_split_impl(self, decl_string, name, args): self.assertTrue( @@ -85,7 +85,7 @@ def test_bug_is_tmpl_inst(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/test_argument_without_name.py b/unittests/test_argument_without_name.py index d288a47c..c251c562 100644 --- a/unittests/test_argument_without_name.py +++ b/unittests/test_argument_without_name.py @@ -10,7 +10,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -45,7 +45,7 @@ def test_argument_without_name(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/test_copy_constructor.py b/unittests/test_copy_constructor.py index 31e95521..4fc13afb 100644 --- a/unittests/test_copy_constructor.py +++ b/unittests/test_copy_constructor.py @@ -10,7 +10,7 @@ from pygccxml import utils -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -63,7 +63,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/test_create_decl_string.py b/unittests/test_create_decl_string.py index 7ab1342d..3f7d54f5 100644 --- a/unittests/test_create_decl_string.py +++ b/unittests/test_create_decl_string.py @@ -9,7 +9,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -48,7 +48,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/test_map_gcc5.py b/unittests/test_map_gcc5.py index b69d3d73..7e135dc5 100644 --- a/unittests/test_map_gcc5.py +++ b/unittests/test_map_gcc5.py @@ -10,7 +10,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -48,7 +48,7 @@ def test_map_gcc5(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/test_utils.py b/unittests/test_utils.py index 3b6809df..ad870f4b 100644 --- a/unittests/test_utils.py +++ b/unittests/test_utils.py @@ -9,7 +9,7 @@ from pygccxml import utils -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def test(self): path = os.path.normpath("/mypath/folder1/folder2/folder3") @@ -28,7 +28,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/test_va_list_tag_removal.py b/unittests/test_va_list_tag_removal.py index 517d224d..e7a131cc 100644 --- a/unittests/test_va_list_tag_removal.py +++ b/unittests/test_va_list_tag_removal.py @@ -11,7 +11,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): """ Test the remove__va_list_tag option @@ -130,7 +130,7 @@ def test_remove_va_list_tag(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/text_reader_tester.py b/unittests/text_reader_tester.py index 9e0b97f4..49107ffd 100644 --- a/unittests/text_reader_tester.py +++ b/unittests/text_reader_tester.py @@ -9,7 +9,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -32,7 +32,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/type_as_exception_bug_tester.py b/unittests/type_as_exception_bug_tester.py index a0967f5b..8a5425de 100644 --- a/unittests/type_as_exception_bug_tester.py +++ b/unittests/type_as_exception_bug_tester.py @@ -10,7 +10,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None def __init__(self, *args): @@ -18,10 +18,10 @@ def __init__(self, *args): self.header = 'type_as_exception_bug.h' def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() def test(self): buggy = self.global_ns.mem_fun('buggy') @@ -36,7 +36,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/type_traits_tester.py b/unittests/type_traits_tester.py index dba7a24e..79e0cc31 100644 --- a/unittests/type_traits_tester.py +++ b/unittests/type_traits_tester.py @@ -12,7 +12,7 @@ from pygccxml import utils -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE declarations = None @@ -22,9 +22,9 @@ def __init__(self, *args): self.declarations = None def setUp(self): - if not tester_t.declarations: - tester_t.declarations = parser.parse([self.header], self.config) - self.declarations = tester_t.declarations + if not Test.declarations: + Test.declarations = parser.parse([self.header], self.config) + self.declarations = Test.declarations def __test_type_category(self, ns_name, controller): ns_control = declarations.find_declaration( @@ -384,9 +384,9 @@ def test(self): # self.declarations = None # def setUp(self): - # if not tester_t.declarations: - # tester_t.declarations = parser.parse([self.header], self.config) - # self.declarations = tester_t.declarations + # if not Test.declarations: + # Test.declarations = parser.parse([self.header], self.config) + # self.declarations = Test.declarations # def test( self ): # x = declarations.find_declaration( self.declarations @@ -440,7 +440,7 @@ def test_get_declaration(self): def create_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(class_traits_tester_t)) - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) suite.addTest(unittest.makeSuite(missing_decls_tester_t)) return suite diff --git a/unittests/undname_creator_tester.py b/unittests/undname_creator_tester.py index 43ac26f0..68b80ff8 100644 --- a/unittests/undname_creator_tester.py +++ b/unittests/undname_creator_tester.py @@ -16,7 +16,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): global_ns = None @@ -83,10 +83,10 @@ def __init__(self, *args): ext) def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - tester_t.global_ns.init_optimizer() + Test.global_ns = declarations.get_global_namespace(decls) + Test.global_ns.init_optimizer() process = subprocess.Popen( args='scons msvc_compiler=%s' % @@ -213,7 +213,7 @@ def dont_test_print(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/unnamed_classes_tester.py b/unittests/unnamed_classes_tester.py index d57d95ee..aa769a14 100644 --- a/unittests/unnamed_classes_tester.py +++ b/unittests/unnamed_classes_tester.py @@ -11,7 +11,7 @@ from pygccxml.declarations import type_traits -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -86,7 +86,7 @@ def test_anonymous_unions(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/vector_traits_tester.py b/unittests/vector_traits_tester.py index 6d01fb46..54061d66 100644 --- a/unittests/vector_traits_tester.py +++ b/unittests/vector_traits_tester.py @@ -9,7 +9,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE global_ns = None @@ -19,10 +19,10 @@ def __init__(self, *args): self.global_ns = None def setUp(self): - if not tester_t.global_ns: + if not Test.global_ns: decls = parser.parse([self.header], self.config) - tester_t.global_ns = declarations.get_global_namespace(decls) - self.global_ns = tester_t.global_ns + Test.global_ns = declarations.get_global_namespace(decls) + self.global_ns = Test.global_ns def validate_yes(self, value_type, container): traits = declarations.vector_traits @@ -80,7 +80,7 @@ def test_element_type(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite diff --git a/unittests/xmlfile_reader_tester.py b/unittests/xmlfile_reader_tester.py index 06076ecb..d2ac052a 100644 --- a/unittests/xmlfile_reader_tester.py +++ b/unittests/xmlfile_reader_tester.py @@ -11,7 +11,7 @@ from pygccxml import declarations -class tester_t(parser_test_case.parser_test_case_t): +class Test(parser_test_case.parser_test_case_t): def __init__(self, *args): parser_test_case.parser_test_case_t.__init__(self, *args) @@ -57,7 +57,7 @@ def test(self): def create_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(tester_t)) + suite.addTest(unittest.makeSuite(Test)) return suite From 4d90cbb27b8d24fa4e7c038ca69829173c3aca8d Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 22:47:55 +0200 Subject: [PATCH 202/268] Ignore all types of coverage files --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index bbcfb715..5f868fc8 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,5 @@ dist build pygccxml.egg-info *.prof -.coverage +.coverage* docs/examples/caching/example.hpp.xml From aacee34c77a348cf7fdeca2f0b5b5feb731b2469 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 22:52:19 +0200 Subject: [PATCH 203/268] Move the pep8 test first. This one is failing often while playing around, and it is annoying to have to wait until the lasts test to see that it is broken --- unittests/test_all.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/test_all.py b/unittests/test_all.py index be0620df..f3409da4 100644 --- a/unittests/test_all.py +++ b/unittests/test_all.py @@ -76,6 +76,7 @@ testers = [ # , demangled_tester # failing right now # , undname_creator_tester # failing right now + pep8_tester, decl_string_tester, declaration_files_tester, declarations_comparison_tester, @@ -128,7 +129,6 @@ inline_specifier_tester, test_create_decl_string, from_future_import_tester, - pep8_tester, example_tester, test_utils, test_va_list_tag_removal, From 4f70f8efa6ff82fe74288529c6bb42059c9b5e21 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 23 Jun 2016 23:06:30 +0200 Subject: [PATCH 204/268] Regroupe some if statements that can be simplified --- pygccxml/declarations/decl_printer.py | 13 +++--- pygccxml/declarations/type_traits_classes.py | 48 ++++++++++---------- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/pygccxml/declarations/decl_printer.py b/pygccxml/declarations/decl_printer.py index bdd2302f..8ee3f217 100644 --- a/pygccxml/declarations/decl_printer.py +++ b/pygccxml/declarations/decl_printer.py @@ -168,13 +168,12 @@ def print_decl_header(self): # Mangled name is only available for functions and variables # when using castxml. print_mangled = False - if "GCC" in utils.xml_generator: - if self.__inst.mangled: - print_mangled = True - elif "CastXML" in utils.xml_generator: - if isinstance(self.__inst, variable_t) or \ - isinstance(self.__inst, calldef_t): - if self.__inst.mangled: + if "GCC" in utils.xml_generator and self.__inst.mangled: + print_mangled = True + elif "CastXML" in utils.xml_generator and \ + (isinstance(self.__inst, variable_t) or + isinstance(self.__inst, calldef_t)) and \ + self.__inst.mangled: print_mangled = True if print_mangled: diff --git a/pygccxml/declarations/type_traits_classes.py b/pygccxml/declarations/type_traits_classes.py index f868c956..0987be43 100644 --- a/pygccxml/declarations/type_traits_classes.py +++ b/pygccxml/declarations/type_traits_classes.py @@ -328,25 +328,26 @@ def __test_trivial(self, source, target): return False else: return True # X => void* - if type_traits.is_pointer(source) and type_traits.is_pointer(target): - if type_traits.is_const(target.base) and \ - type_traits.is_same(source.base, target.base.base): + if type_traits.is_pointer(source) and \ + type_traits.is_pointer(target) and \ + type_traits.is_const(target.base) and \ + type_traits.is_same(source.base, target.base.base): return True # X* => const X* if type_traits.is_reference(source) and \ - type_traits.is_reference(target): - if type_traits.is_const(target.base) and \ - type_traits.is_same(source.base, target.base.base): + type_traits.is_reference(target) and \ + type_traits.is_const(target.base) and \ + type_traits.is_same(source.base, target.base.base): return True # X& => const X& if not type_traits.is_const(source) and \ type_traits.is_array(source) and \ - type_traits.is_pointer(target): - if type_traits.is_same( + type_traits.is_pointer(target) and \ + type_traits.is_same( type_traits.base_type(source), target.base): return True # X[2] => X* if type_traits.is_array(source) and \ type_traits.is_pointer(target) and \ - type_traits.is_const(target.base): - if type_traits.is_same( + type_traits.is_const(target.base) and \ + type_traits.is_same( type_traits.base_type(source), target.base.base): return True @@ -583,8 +584,8 @@ def is_convertible(self): # may be target is class too, so in this case we should check whether # is has constructor from source - if isinstance(target, cpptypes.declarated_t): - if isinstance(target.declaration, class_declaration.class_t): + if isinstance(target, cpptypes.declarated_t) and \ + isinstance(target.declaration, class_declaration.class_t): constructors = scopedef.find_all_declarations( target.declaration.declarations, decl_type=calldef_members.constructor_t, @@ -669,19 +670,16 @@ def is_noncopyable(class_): base_copy_ = find_copy_constructor(base_desc.related_class) - if base_copy_: - - if base_copy_.access_type == 'private': - logger.debug( - true_header + - "there is private copy constructor") - return True - else: - if __is_noncopyable_single(base_desc.related_class): - logger.debug( - true_header + - "__is_noncopyable_single returned True") - return True + if base_copy_ and base_copy_.access_type == 'private': + logger.debug( + true_header + + "there is private copy constructor") + return True + elif __is_noncopyable_single(base_desc.related_class): + logger.debug( + true_header + + "__is_noncopyable_single returned True") + return True if __is_noncopyable_single(base_desc.related_class): logger.debug( From edbee645210fece0fddac14d75e20b1f438a732b Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 24 Jun 2016 12:14:43 +0200 Subject: [PATCH 205/268] Perf: create the integral_def tuple only once The is_integral method can be called more than 500 times on a simple file by pyplusplus. Creating the tuple only once during the module import makes a 2.1% speed gain. --- pygccxml/declarations/type_traits.py | 48 +++++++++++++++++----------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 2faa8b1c..bd291aba 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -140,26 +140,36 @@ def is_void_pointer(type_): return is_same(type_, cpptypes.pointer_t(cpptypes.void_t())) +# Tuple of integral c++ types. +_integral_def = ( + create_cv_types(cpptypes.char_t()) + + create_cv_types(cpptypes.unsigned_char_t()) + + create_cv_types(cpptypes.signed_char_t()) + + create_cv_types(cpptypes.wchar_t()) + + create_cv_types(cpptypes.short_int_t()) + + create_cv_types(cpptypes.short_unsigned_int_t()) + + create_cv_types(cpptypes.bool_t()) + + create_cv_types(cpptypes.int_t()) + + create_cv_types(cpptypes.unsigned_int_t()) + + create_cv_types(cpptypes.long_int_t()) + + create_cv_types(cpptypes.long_unsigned_int_t()) + + create_cv_types(cpptypes.long_long_int_t()) + + create_cv_types(cpptypes.long_long_unsigned_int_t()) + + create_cv_types(cpptypes.int128_t()) + + create_cv_types(cpptypes.uint128_t())) + + def is_integral(type_): - """returns True, if type represents C++ integral type, False otherwise""" - integral_def = ( - create_cv_types(cpptypes.char_t()) + - create_cv_types(cpptypes.unsigned_char_t()) + - create_cv_types(cpptypes.signed_char_t()) + - create_cv_types(cpptypes.wchar_t()) + - create_cv_types(cpptypes.short_int_t()) + - create_cv_types(cpptypes.short_unsigned_int_t()) + - create_cv_types(cpptypes.bool_t()) + - create_cv_types(cpptypes.int_t()) + - create_cv_types(cpptypes.unsigned_int_t()) + - create_cv_types(cpptypes.long_int_t()) + - create_cv_types(cpptypes.long_unsigned_int_t()) + - create_cv_types(cpptypes.long_long_int_t()) + - create_cv_types(cpptypes.long_long_unsigned_int_t()) + - create_cv_types(cpptypes.int128_t()) + - create_cv_types(cpptypes.uint128_t())) - - return remove_alias(type_) in integral_def + """ + Check if type is a C++ integral type + + Args: + type_ (type_t): The type to be checked + + Returns: + bool: True if type is a C++ integral type, False otherwise. + """ + return remove_alias(type_) in _integral_def def is_floating_point(type_): From 8386aa6c7ac98055fdd1121e06801a88fe8b50b7 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 24 Jun 2016 12:22:35 +0200 Subject: [PATCH 206/268] Rename method, cleanup indentation --- pygccxml/declarations/type_traits.py | 56 ++++++++++++++-------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index bd291aba..134b8587 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -84,14 +84,16 @@ def base_type(type_): return types[-1] -def create_cv_types(base): - """implementation details""" +def _create_cv_types(base): + """ + Implementation detail. + + """ return ( [base, - cpptypes.const_t( - base), - cpptypes.volatile_t(base), - cpptypes.volatile_t(cpptypes.const_t(base))] + cpptypes.const_t(base), + cpptypes.volatile_t(base), + cpptypes.volatile_t(cpptypes.const_t(base))] ) @@ -125,14 +127,12 @@ def does_match_definition(given, main, secondary): def is_bool(type_): """returns True, if type represents `bool`, False otherwise""" - return remove_alias(type_) in create_cv_types( - cpptypes.bool_t()) + return remove_alias(type_) in _create_cv_types(cpptypes.bool_t()) def is_void(type_): """returns True, if type represents `void`, False otherwise""" - return remove_alias(type_) in create_cv_types( - cpptypes.void_t()) + return remove_alias(type_) in _create_cv_types(cpptypes.void_t()) def is_void_pointer(type_): @@ -142,21 +142,21 @@ def is_void_pointer(type_): # Tuple of integral c++ types. _integral_def = ( - create_cv_types(cpptypes.char_t()) + - create_cv_types(cpptypes.unsigned_char_t()) + - create_cv_types(cpptypes.signed_char_t()) + - create_cv_types(cpptypes.wchar_t()) + - create_cv_types(cpptypes.short_int_t()) + - create_cv_types(cpptypes.short_unsigned_int_t()) + - create_cv_types(cpptypes.bool_t()) + - create_cv_types(cpptypes.int_t()) + - create_cv_types(cpptypes.unsigned_int_t()) + - create_cv_types(cpptypes.long_int_t()) + - create_cv_types(cpptypes.long_unsigned_int_t()) + - create_cv_types(cpptypes.long_long_int_t()) + - create_cv_types(cpptypes.long_long_unsigned_int_t()) + - create_cv_types(cpptypes.int128_t()) + - create_cv_types(cpptypes.uint128_t())) + _create_cv_types(cpptypes.char_t()) + + _create_cv_types(cpptypes.unsigned_char_t()) + + _create_cv_types(cpptypes.signed_char_t()) + + _create_cv_types(cpptypes.wchar_t()) + + _create_cv_types(cpptypes.short_int_t()) + + _create_cv_types(cpptypes.short_unsigned_int_t()) + + _create_cv_types(cpptypes.bool_t()) + + _create_cv_types(cpptypes.int_t()) + + _create_cv_types(cpptypes.unsigned_int_t()) + + _create_cv_types(cpptypes.long_int_t()) + + _create_cv_types(cpptypes.long_unsigned_int_t()) + + _create_cv_types(cpptypes.long_long_int_t()) + + _create_cv_types(cpptypes.long_long_unsigned_int_t()) + + _create_cv_types(cpptypes.int128_t()) + + _create_cv_types(cpptypes.uint128_t())) def is_integral(type_): @@ -176,9 +176,9 @@ def is_floating_point(type_): """returns True, if type represents C++ floating point type, False otherwise""" float_def = ( - create_cv_types(cpptypes.float_t()) + - create_cv_types(cpptypes.double_t()) + - create_cv_types(cpptypes.long_double_t())) + _create_cv_types(cpptypes.float_t()) + + _create_cv_types(cpptypes.double_t()) + + _create_cv_types(cpptypes.long_double_t())) return remove_alias(type_) in float_def From 1001c112891f0d5a3b7b480d9cc5b99a341a4e08 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 24 Jun 2016 12:33:52 +0200 Subject: [PATCH 207/268] Optimize all the other calls to _create_cv_types --- pygccxml/declarations/type_traits.py | 75 +++++++++++++++++----------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 134b8587..11d3f28a 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -96,6 +96,32 @@ def _create_cv_types(base): cpptypes.volatile_t(cpptypes.const_t(base))] ) +# Some tuples containing combinations of different types +# These are created once the module is loaded, so that when they are used +# they do not need to be re-created. +_void_def = _create_cv_types(cpptypes.void_t()) +_bool_def = _create_cv_types(cpptypes.bool_t()) +_float_def = ( + _create_cv_types(cpptypes.float_t()) + + _create_cv_types(cpptypes.double_t()) + + _create_cv_types(cpptypes.long_double_t())) +_integral_def = ( + _create_cv_types(cpptypes.char_t()) + + _create_cv_types(cpptypes.unsigned_char_t()) + + _create_cv_types(cpptypes.signed_char_t()) + + _create_cv_types(cpptypes.wchar_t()) + + _create_cv_types(cpptypes.short_int_t()) + + _create_cv_types(cpptypes.short_unsigned_int_t()) + + _create_cv_types(cpptypes.bool_t()) + + _create_cv_types(cpptypes.int_t()) + + _create_cv_types(cpptypes.unsigned_int_t()) + + _create_cv_types(cpptypes.long_int_t()) + + _create_cv_types(cpptypes.long_unsigned_int_t()) + + _create_cv_types(cpptypes.long_long_int_t()) + + _create_cv_types(cpptypes.long_long_unsigned_int_t()) + + _create_cv_types(cpptypes.int128_t()) + + _create_cv_types(cpptypes.uint128_t())) + def does_match_definition(given, main, secondary): """implementation details""" @@ -126,13 +152,29 @@ def does_match_definition(given, main, secondary): def is_bool(type_): - """returns True, if type represents `bool`, False otherwise""" - return remove_alias(type_) in _create_cv_types(cpptypes.bool_t()) + """ + Check if type is of boolean type. + + Args: + type_ (type_t): The type to be checked + + Returns: + bool: True if type is a boolean, False otherwise. + """ + return remove_alias(type_) in _bool_def def is_void(type_): - """returns True, if type represents `void`, False otherwise""" - return remove_alias(type_) in _create_cv_types(cpptypes.void_t()) + """ + Check if type is of void type. + + Args: + type_ (type_t): The type to be checked + + Returns: + bool: True if type is void, False otherwise. + """ + return remove_alias(type_) in _void_def def is_void_pointer(type_): @@ -140,25 +182,6 @@ def is_void_pointer(type_): return is_same(type_, cpptypes.pointer_t(cpptypes.void_t())) -# Tuple of integral c++ types. -_integral_def = ( - _create_cv_types(cpptypes.char_t()) + - _create_cv_types(cpptypes.unsigned_char_t()) + - _create_cv_types(cpptypes.signed_char_t()) + - _create_cv_types(cpptypes.wchar_t()) + - _create_cv_types(cpptypes.short_int_t()) + - _create_cv_types(cpptypes.short_unsigned_int_t()) + - _create_cv_types(cpptypes.bool_t()) + - _create_cv_types(cpptypes.int_t()) + - _create_cv_types(cpptypes.unsigned_int_t()) + - _create_cv_types(cpptypes.long_int_t()) + - _create_cv_types(cpptypes.long_unsigned_int_t()) + - _create_cv_types(cpptypes.long_long_int_t()) + - _create_cv_types(cpptypes.long_long_unsigned_int_t()) + - _create_cv_types(cpptypes.int128_t()) + - _create_cv_types(cpptypes.uint128_t())) - - def is_integral(type_): """ Check if type is a C++ integral type @@ -175,12 +198,8 @@ def is_integral(type_): def is_floating_point(type_): """returns True, if type represents C++ floating point type, False otherwise""" - float_def = ( - _create_cv_types(cpptypes.float_t()) + - _create_cv_types(cpptypes.double_t()) + - _create_cv_types(cpptypes.long_double_t())) - return remove_alias(type_) in float_def + return remove_alias(type_) in _float_def def is_arithmetic(type_): From 404cbda549e53a32d422e4c16f02f7194e1d97b7 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Fri, 24 Jun 2016 12:48:43 +0200 Subject: [PATCH 208/268] Cache decl_name and partial_dcl_name in type_t These functions can be called up to 5000 times in simple cases. Performance gain is around 1% --- pygccxml/declarations/cpptypes.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/pygccxml/declarations/cpptypes.py b/pygccxml/declarations/cpptypes.py index 60e7c587..72c7b9a0 100644 --- a/pygccxml/declarations/cpptypes.py +++ b/pygccxml/declarations/cpptypes.py @@ -19,6 +19,8 @@ def __init__(self): self.cache = algorithms_cache.type_algs_cache_t() self._byte_size = 0 self._byte_align = 0 + self._decl_string = None + self._partial_decl_string = None def __str__(self): res = self.decl_string @@ -47,11 +49,19 @@ def build_decl_string(self, with_defaults=True): @property def decl_string(self): - return self.build_decl_string() + if self._decl_string is None: + self._decl_string = self.build_decl_string() + return self._decl_string + else: + return self._decl_string @property def partial_decl_string(self): - return self.build_decl_string(False) + if self._partial_decl_string is None: + self._partial_decl_string = self.build_decl_string(False) + return self._partial_decl_string + else: + return self._partial_decl_string def _clone_impl(self): raise NotImplementedError() From 870d38e5c8bdc31865c1b95cf07a83be729c391a Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 25 Jun 2016 16:25:09 +0200 Subject: [PATCH 209/268] Use more pythonic variable names --- .../get_dll_exported_symbols.py | 28 +++++++++---------- pygccxml/declarations/xml_generators.py | 10 +++---- pygccxml/parser/scanner.py | 10 +++---- unittests/core_tester.py | 16 +++++------ unittests/type_as_exception_bug_tester.py | 4 +-- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/pygccxml/binary_parsers/get_dll_exported_symbols.py b/pygccxml/binary_parsers/get_dll_exported_symbols.py index 11ccc291..e36e3f6a 100644 --- a/pygccxml/binary_parsers/get_dll_exported_symbols.py +++ b/pygccxml/binary_parsers/get_dll_exported_symbols.py @@ -194,23 +194,23 @@ def read_export_table(dll_name, mmap=False, use_kernel=False): else: if not use_kernel: - fileH = open(dll_name) - if fileH is None: + fileh = open(dll_name) + if fileh is None: raise DllException("Cant load dll") import mmap - m = mmap.mmap(fileH.fileno(), 0, None, mmap.ACCESS_READ) + m = mmap.mmap(fileh.fileno(), 0, None, mmap.ACCESS_READ) # id(m)+8 sucks, is there better way? base_addr = ctypes.cast(id(m) + 8, ctypes.POINTER(ctypes.c_int))[0] else: kernel32 = ctypes.windll.kernel32 if kernel32 is None: raise DllException("cant load kernel") - fileH = kernel32.CreateFileA(dll_name, 0x00120089, 1, 0, 3, 0, 0) - if fileH == 0: + fileh = kernel32.CreateFileA(dll_name, 0x00120089, 1, 0, 3, 0, 0) + if fileh == 0: raise DllException( "Cant open, errcode = %d" % kernel32.GetLastError()) - mapH = kernel32.CreateFileMappingW(fileH, 0, 0x8000002, 0, 0, 0) + mapH = kernel32.CreateFileMappingW(fileh, 0, 0x8000002, 0, 0, 0) if mapH == 0: raise DllException( "Cant mmap, errocode = %d" % @@ -246,12 +246,12 @@ def read_export_table(dll_name, mmap=False, use_kernel=False): (1, "Base", base_addr), (1, "Rva"), (1, "LastRvaSection", 0)) - ImageRvaToVa = prototype(('ImageRvaToVa', dbghelp), paramflags) + image_rva_to_va = prototype(('ImageRvaToVa', dbghelp), paramflags) def cast_rva(rva, type_): va = base_addr + rva if mmap and va > pimage_nt_header: - va = ImageRvaToVa(Rva=rva) + va = image_rva_to_va(Rva=rva) if va == 0: raise DllException("ImageRvaToVa failed") return ctypes.cast(va, type_) @@ -277,10 +277,10 @@ def cast_rva(rva, type_): exports_dd.VirtualAddress, PIMAGE_EXPORT_DIRECTORY)[0] - nNames = export_dir.NumberOfNames - if nNames > 0: - PNamesType = ctypes.POINTER(ctypes.c_int * nNames) - names = cast_rva(export_dir.AddressOfNames, PNamesType)[0] + n_names = export_dir.NumberOfNames + if n_names > 0: + p_names_type = ctypes.POINTER(ctypes.c_int * n_names) + names = cast_rva(export_dir.AddressOfNames, p_names_type)[0] for rva in names: name = cast_rva(rva, ctypes.c_char_p).value ret_val.append(name) @@ -289,10 +289,10 @@ def cast_rva(rva, type_): if use_kernel: kernel32.UnmapViewOfFile(base_addr) kernel32.CloseHandle(mapH) - kernel32.CloseHandle(fileH) + kernel32.CloseHandle(fileh) else: m.close() - fileH.close() + fileh.close() return ret_val diff --git a/pygccxml/declarations/xml_generators.py b/pygccxml/declarations/xml_generators.py index 831ebd08..4d3e4d12 100644 --- a/pygccxml/declarations/xml_generators.py +++ b/pygccxml/declarations/xml_generators.py @@ -8,17 +8,17 @@ """ -GCC_XML_06 = "GCC-XML 0.6" -GCC_XML_07 = "GCC-XML 0.7" -GCC_XML_09 = "GCC-XML 0.9" -GCC_XML_09_BUGGY = "GCC-XML 0.9 BUGGY" +gccxml_06 = "GCC-XML 0.6" +gccxml_07 = "GCC-XML 0.7" +gccxml_09 = "GCC-XML 0.9" +gccxml_09_buggy = "GCC-XML 0.9 BUGGY" # revision 122: # After this fix, all constructors and destructors that exist for a class # are dumped whether the user declared them or not. Those that were # implicitly declared by the xml_generator are marked as "artificial". # CastXML has no version number for the moment so "None" is used. -CASTXML_None = "CastXML None" +castxml_none = "CastXML None" def on_missing_functionality(xml_generator, functionality): diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index 61456673..6df8374b 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -616,22 +616,22 @@ def __read_version(self, attrs): version = float(version_str) if version is None: logger.debug('GCCXML version - 0.6') - utils.xml_generator = declarations.xml_generators.GCC_XML_06 + utils.xml_generator = declarations.xml_generators.gccxml_06 elif version <= 1.114: logger.debug('GCCXML version - 0.7') - utils.xml_generator = declarations.xml_generators.GCC_XML_07 + utils.xml_generator = declarations.xml_generators.gccxml_07 elif 1.115 <= version <= 1.126: logger.debug('GCCXML version - 0.9 BUGGY ( %s )', version_str) - utils.xml_generator = declarations.xml_generators.GCC_XML_09_BUGGY + utils.xml_generator = declarations.xml_generators.gccxml_09_buggy elif 1.126 <= version <= 1.135: logger.debug('GCCXML version - 0.9 ( %s )', version_str) - utils.xml_generator = declarations.xml_generators.GCC_XML_09 + utils.xml_generator = declarations.xml_generators.gccxml_09 else: # CastXML starts with revision 1.136, but still writes the GCCXML # tag and the 0.9 version number in the XML files for backward # compatibility. logger.debug('CASTXML version - None ( %s )', version_str) - utils.xml_generator = declarations.xml_generators.CASTXML_None + utils.xml_generator = declarations.xml_generators.castxml_none utils.xml_output_version = version def __update_unnamed_class(self, decl, attrs): diff --git a/unittests/core_tester.py b/unittests/core_tester.py index e079ad93..8b5f7c68 100644 --- a/unittests/core_tester.py +++ b/unittests/core_tester.py @@ -72,19 +72,19 @@ def test_nss_join(self): ns is ns12.parent is ns22.parent is ns32.parent), 'There are 2 or more instances of ns namespace.') - E11 = self.global_ns.enum(enums[0]) - E21 = self.global_ns.enum(enums[1]) - E31 = self.global_ns.enum(enums[2]) + e11 = self.global_ns.enum(enums[0]) + e21 = self.global_ns.enum(enums[1]) + e31 = self.global_ns.enum(enums[2]) self.assertTrue( - E11.parent is E21.parent is E31.parent, + e11.parent is e21.parent is e31.parent, 'There are 2 or more instances of global namespace.') - nsE12 = self.global_ns.enum(enums[3]) - nsE23 = self.global_ns.enum(enums[4]) - nsE33 = self.global_ns.enum(enums[5]) + nse12 = self.global_ns.enum(enums[3]) + nse23 = self.global_ns.enum(enums[4]) + nse33 = self.global_ns.enum(enums[5]) self.assertTrue( ns and ( - ns is nsE12.parent is nsE23.parent is nsE33.parent), + ns is nse12.parent is nse23.parent is nse33.parent), 'There are 2 or more instances of ns namespace.') def _test_ns_membership(self, ns, enum_name): diff --git a/unittests/type_as_exception_bug_tester.py b/unittests/type_as_exception_bug_tester.py index 8a5425de..d499d3ba 100644 --- a/unittests/type_as_exception_bug_tester.py +++ b/unittests/type_as_exception_bug_tester.py @@ -25,13 +25,13 @@ def setUp(self): def test(self): buggy = self.global_ns.mem_fun('buggy') - ExpressionError = self.global_ns.class_('ExpressionError') + expression_error = self.global_ns.class_('ExpressionError') self.assertTrue(len(buggy.exceptions) == 1) err = buggy.exceptions[0] self.assertTrue(declarations.is_reference(err)) err = declarations.remove_declarated( declarations.remove_reference(err)) - self.assertTrue(err is ExpressionError) + self.assertTrue(err is expression_error) def create_suite(): From 89332aa3c3ae2fc3aa90e4f078de1a489dc60129 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 25 Jun 2016 16:49:55 +0200 Subject: [PATCH 210/268] Remove globals in templates.py There is no need for global variables here. We are only using __THE_PARSER, and do not need to modify it from within one of the functions. --- pygccxml/declarations/templates.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pygccxml/declarations/templates.py b/pygccxml/declarations/templates.py index 2fe34d17..9b6c7427 100644 --- a/pygccxml/declarations/templates.py +++ b/pygccxml/declarations/templates.py @@ -30,7 +30,6 @@ def is_instantiation(decl_string): :rtype: bool """ - global __THE_PARSER return __THE_PARSER.has_pattern(decl_string) @@ -41,7 +40,6 @@ def name(decl_string): :type decl_string: str :rtype: str """ - global __THE_PARSER return __THE_PARSER.name(decl_string) @@ -52,25 +50,21 @@ def args(decl_string): :type decl_string: `str` :rtype: [`str`] """ - global __THE_PARSER return __THE_PARSER.args(decl_string) def split(decl_string): """returns (name, [arguments] )""" - global __THE_PARSER return __THE_PARSER.split(decl_string) def split_recursive(decl_string): """returns [(name, [arguments])]""" - global __THE_PARSER return __THE_PARSER.split_recursive(decl_string) def join(name, args): """returns name< argument_1, argument_2, ..., argument_n >""" - global __THE_PARSER return __THE_PARSER.join(name, args) @@ -80,5 +74,4 @@ def normalize(decl_string): this functionality allows to implement comparison of 2 different string which are actually same: x::y< z > and x::y """ - global __THE_PARSER return __THE_PARSER.normalize(decl_string) From 2c4772725619c00e35880ec085556a3c0469f7b8 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 25 Jun 2016 16:58:48 +0200 Subject: [PATCH 211/268] Remove globals in call_invocation.py There is no need for global variables here. We are only using __THE_PARSER, and do not need to modify it from within one of the functions. --- pygccxml/declarations/call_invocation.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pygccxml/declarations/call_invocation.py b/pygccxml/declarations/call_invocation.py index b5b550e5..d1ce744a 100644 --- a/pygccxml/declarations/call_invocation.py +++ b/pygccxml/declarations/call_invocation.py @@ -34,8 +34,6 @@ def is_call_invocation(declaration_string): :rtype: bool """ - - global __THE_PARSER return __THE_PARSER.has_pattern(declaration_string) @@ -47,8 +45,6 @@ def name(declaration_string): :rtype: str """ - - global __THE_PARSER return __THE_PARSER.name(declaration_string) @@ -60,8 +56,6 @@ def args(declaration_string): :rtype: [str] """ - - global __THE_PARSER return __THE_PARSER.args(declaration_string) NOT_FOUND = __THE_PARSER.NOT_FOUND @@ -75,8 +69,6 @@ def find_args(text, start=None): :rtype: [ arguments ] or :data:NOT_FOUND if arguments could not be found. """ - - global __THE_PARSER return __THE_PARSER.find_args(text, start) @@ -85,8 +77,6 @@ def split(declaration_string): Returns (name, [arguments] ) """ - - global __THE_PARSER return __THE_PARSER.split(declaration_string) @@ -95,8 +85,6 @@ def split_recursive(declaration_string): Returns [(name, [arguments])]. """ - - global __THE_PARSER return __THE_PARSER.split_recursive(declaration_string) @@ -105,6 +93,4 @@ def join(name, args, arg_separator=None): Returns name( argument_1, argument_2, ..., argument_n ). """ - - global __THE_PARSER return __THE_PARSER.join(name, args, arg_separator) From 05bda3d6c025f30580b56817b83dbaec41f4a716 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 25 Jun 2016 16:59:12 +0200 Subject: [PATCH 212/268] Remove global in binary parser There is no need for a global variable here. --- pygccxml/binary_parsers/parsers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pygccxml/binary_parsers/parsers.py b/pygccxml/binary_parsers/parsers.py index 024d8e5a..b8e915e6 100644 --- a/pygccxml/binary_parsers/parsers.py +++ b/pygccxml/binary_parsers/parsers.py @@ -203,7 +203,6 @@ class dll_file_parser_t(formated_mapping_parser_t): """parser for Windows .dll file""" def __init__(self, global_ns, map_file_path): - global dll_file_parser_warning warnings.warn(dll_file_parser_warning, LicenseWarning) formated_mapping_parser_t.__init__( self, From fb692ef584aacd8aa8d46e6e93e4dc4677f73b5d Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 25 Jun 2016 17:34:38 +0200 Subject: [PATCH 213/268] Remove global in container_traits This is not needed here, we are just calling the find_container_traits function --- pygccxml/declarations/container_traits.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pygccxml/declarations/container_traits.py b/pygccxml/declarations/container_traits.py index 211dc611..4139cf88 100644 --- a/pygccxml/declarations/container_traits.py +++ b/pygccxml/declarations/container_traits.py @@ -70,7 +70,6 @@ def decorated_call_suffix(self, cls_name, text, doit): return answer def erase_call(self, cls_name): - global find_container_traits c_traits = find_container_traits(cls_name) if not c_traits: return cls_name From 208be38ae2daace094d0bafd8da012395adf2b83 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 25 Jun 2016 21:58:53 +0200 Subject: [PATCH 214/268] Use more pythonic variable names --- docs/examples/searching/example.py | 20 +++++++++---------- .../get_dll_exported_symbols.py | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/examples/searching/example.py b/docs/examples/searching/example.py index ba596254..56a1029d 100644 --- a/docs/examples/searching/example.py +++ b/docs/examples/searching/example.py @@ -38,19 +38,19 @@ # Search for the function by name criteria = declarations.calldef_matcher(name="func1") -funcA = declarations.matcher.get_single(criteria, ns_namespace) +func1 = declarations.matcher.get_single(criteria, ns_namespace) # Search for functions which return an int criteria = declarations.calldef_matcher(return_type="int") -funcB = declarations.matcher.get_single(criteria, ns_namespace) +func2 = declarations.matcher.get_single(criteria, ns_namespace) # Search for functions which return an int, using the cpptypes class criteria = declarations.calldef_matcher(return_type=int_type) -funcC = declarations.matcher.get_single(criteria, ns_namespace) +func3 = declarations.matcher.get_single(criteria, ns_namespace) -print(funcA) -print(funcB) -print(funcC) +print(func1) +print(func2) +print(func3) # This prints: # int ns::func1(int a) [free function] @@ -59,11 +59,11 @@ # Search for functions which return a double. Two functions will be found criteria = declarations.calldef_matcher(return_type=double_type) -funcD = declarations.matcher.find(criteria, ns_namespace) +func4 = declarations.matcher.find(criteria, ns_namespace) -print(len(funcD)) -print(funcD[0]) -print(funcD[1]) +print(len(func4)) +print(func4[0]) +print(func4[1]) # This prints: # 2 diff --git a/pygccxml/binary_parsers/get_dll_exported_symbols.py b/pygccxml/binary_parsers/get_dll_exported_symbols.py index e36e3f6a..86842706 100644 --- a/pygccxml/binary_parsers/get_dll_exported_symbols.py +++ b/pygccxml/binary_parsers/get_dll_exported_symbols.py @@ -210,13 +210,13 @@ def read_export_table(dll_name, mmap=False, use_kernel=False): raise DllException( "Cant open, errcode = %d" % kernel32.GetLastError()) - mapH = kernel32.CreateFileMappingW(fileh, 0, 0x8000002, 0, 0, 0) - if mapH == 0: + maph = kernel32.CreateFileMappingW(fileh, 0, 0x8000002, 0, 0, 0) + if maph == 0: raise DllException( "Cant mmap, errocode = %d" % kernel32.GetLastError()) base_addr = ctypes.windll.kernel32.MapViewOfFile( - mapH, 0x4, 0, 0, 0) + maph, 0x4, 0, 0, 0) if base_addr == 0: raise DllException( "Cant mmap(2), errocode = %d" % From cdde8dbe66f4312800f5cfaf3e01752698045040 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 26 Jun 2016 10:57:17 +0200 Subject: [PATCH 215/268] Deprecate the binary_parsers module See the changelog for more information --- CHANGELOG.md | 21 +++++++++++++++++---- pygccxml/binary_parsers/__init__.py | 11 +++++++++++ pygccxml/binary_parsers/parsers.py | 7 +++++++ pygccxml/binary_parsers/undname.py | 8 ++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5160379..c480fddb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,10 +21,23 @@ Version 1.8.0 (not yet released) * [Removals] Remove compiler attribute in declarations.py and gccxml_path from config.py These were deprecated in pygccxml v1.7.0, and definitively removed for v1.8.0 -* [Deprecations] A bunch of attributes and methods were deprecated. - They will throw a warning when used with pygccxml 1.8.0, and will be removed - in version 1.9.0. - * In ``class_declaration_t``` and ```class_t```: +* [Deprecations] + * The ```binary_parsers``` module was deprecated. It seems that this module is not + used by other third-party projects, at least a quick search on GitHub + did not give any interesting usage. Also, this code is not tested, and + there seem to be some undefined variables, so it is highly probable that this + module is not working anyway. + I do not want to put much efforts in maintaining this module, but concentrate + on improving pygccxml's core features. If somebody wants to revive this + module it can still be done in a separate project. + Thus, the 3 following functions are now deprecated and will be removed in + pygccxml 1.9.0: ```merge_information```, ```undecorate_blob``` and ```format_decl```. + The ```undname_creator_t``` class is also deprecated for the same reason. + + * A bunch of attributes and methods were deprecated. + They will throw a warning when used with pygccxml 1.8.0, and will be removed + in version 1.9.0. + * In ```class_declaration_t``` and ```class_t```: - decl.container_traits attribute => declarations.find_container_traits(decl) * In ```class_t``` - decl.find_noncopyable_vars() method => declarations.find_noncopyable_vars(decl) diff --git a/pygccxml/binary_parsers/__init__.py b/pygccxml/binary_parsers/__init__.py index 8ab29ba2..a833ee20 100644 --- a/pygccxml/binary_parsers/__init__.py +++ b/pygccxml/binary_parsers/__init__.py @@ -11,6 +11,7 @@ :func:`pygccxml.binary_parsers.parsers.merge_information`. """ +import warnings from .undname import undname_creator_t from .parsers import merge_information @@ -19,6 +20,11 @@ def undecorate_blob(blob): """Returns undecorated/unmangled string, created from blob(exported symbol name) """ + warnings.warn( + "undecorate_blob is deprecated.\n" + + "Please have a look at the changelog for an explanation (since 1.8.0)", + DeprecationWarning) + return undname_creator_t().undecorate_blob(blob) @@ -28,4 +34,9 @@ def format_decl(decl, hint=None): rules :param hint: valid values are: "msvc" and "nm" """ + warnings.warn( + "format_decl is deprecated.\n" + + "Please have a look at the changelog for an explanation (since 1.8.0)", + DeprecationWarning) + return undname_creator_t().format_decl(decl, hint=hint) diff --git a/pygccxml/binary_parsers/parsers.py b/pygccxml/binary_parsers/parsers.py index b8e915e6..038ff7fe 100644 --- a/pygccxml/binary_parsers/parsers.py +++ b/pygccxml/binary_parsers/parsers.py @@ -423,8 +423,15 @@ def merge(self, smbl): def merge_information(global_ns, fname, runs_under_unittest=False): + """high level function - select the appropriate binary file parser and integrates the information from the file to the declarations tree. """ + + warnings.warn( + "merge_information is deprecated.\n" + + "Please have a look at the changelog for an explanation (since 1.8.0)", + DeprecationWarning) + ext = os.path.splitext(fname)[1] if '.dll' == ext: diff --git a/pygccxml/binary_parsers/undname.py b/pygccxml/binary_parsers/undname.py index d5568891..34d5820a 100644 --- a/pygccxml/binary_parsers/undname.py +++ b/pygccxml/binary_parsers/undname.py @@ -18,6 +18,7 @@ import os import re import ctypes +import warnings from .. import declarations @@ -94,6 +95,13 @@ class undname_creator_t(object): """ def __init__(self): + + warnings.warn( + "undname_creator_t is deprecated.\n" + + "Please have a look at the changelog for an explanation " + + "(since 1.8.0)", + DeprecationWarning) + if 'nt' == os.name: import ctypes.wintypes self.__undname = ctypes.windll.dbghelp.UnDecorateSymbolName From 449d6b3a9426ff4d97bec3aeb40c48f5a720163a Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 26 Jun 2016 12:35:03 +0200 Subject: [PATCH 216/268] Use static methods whenever possible This is only done on methods which are not part of the public API --- pygccxml/parser/directory_cache.py | 6 ++- pygccxml/parser/patcher.py | 18 +++++--- pygccxml/parser/scanner.py | 51 +++++++++++++++-------- unittests/declarations_cache_tester.py | 3 +- unittests/file_cache_tester.py | 3 +- unittests/find_container_traits_tester.py | 3 +- 6 files changed, 56 insertions(+), 28 deletions(-) diff --git a/pygccxml/parser/directory_cache.py b/pygccxml/parser/directory_cache.py index 960805e9..0fe91040 100644 --- a/pygccxml/parser/directory_cache.py +++ b/pygccxml/parser/directory_cache.py @@ -329,7 +329,8 @@ def _remove_entry(self, source_file, key): except OSError as e: print("Could not remove cache file (%s)" % e) - def _create_cache_key(self, source_file): + @staticmethod + def _create_cache_key(source_file): """ return the cache key for a header file. @@ -351,7 +352,8 @@ def _create_cache_filename(self, source_file): res = self._create_cache_key(source_file) + ".cache" return os.path.join(self.__dir, res) - def _create_config_signature(self, config): + @staticmethod + def _create_config_signature(config): """ return the signature for a config object. diff --git a/pygccxml/parser/patcher.py b/pygccxml/parser/patcher.py index 3c46601b..10cc6791 100644 --- a/pygccxml/parser/patcher.py +++ b/pygccxml/parser/patcher.py @@ -36,13 +36,15 @@ def __find_fixer(self, func, arg): else: return None - def __join_names(self, prefix, suffix): + @staticmethod + def __join_names(prefix, suffix): if prefix == '::': return '::' + suffix else: return prefix + '::' + suffix - def __is_unqualified_enum(self, func, arg): + @staticmethod + def __is_unqualified_enum(func, arg): type_ = declarations.remove_reference( declarations.remove_cv(arg.decl_type)) if not declarations.is_enum(type_): @@ -66,7 +68,8 @@ def __fix_unqualified_enum(self, func, arg): qualifier_decl_string, arg.default_value.split('::')[-1]) - def __is_invalid_integral(self, func, arg): + @staticmethod + def __is_invalid_integral(func, arg): type_ = declarations.remove_reference( declarations.remove_cv(arg.decl_type)) if not declarations.is_integral(type_): @@ -156,7 +159,8 @@ def __find_enum(self, scope, default_value): return enum return None - def __is_double_call(self, func, arg): + @staticmethod + def __is_double_call(func, arg): call_invocation = declarations.call_invocation dv = arg.default_value found1 = call_invocation.find_args(dv) @@ -169,7 +173,8 @@ def __is_double_call(self, func, arg): args2 = call_invocation.args(dv[found2[0]: found2[1] + 1]) return len(args1) == len(args2) - def __fix_double_call(self, func, arg): + @staticmethod + def __fix_double_call(func, arg): call_invocation = declarations.call_invocation dv = arg.default_value found1 = call_invocation.find_args(dv) @@ -178,7 +183,8 @@ def __fix_double_call(self, func, arg): args2 = call_invocation.args(dv[found2[0]: found2[1] + 1]) return call_invocation.join(dv[:found1[0]], args2) - def __is_constructor_call(self, func, arg): + @staticmethod + def __is_constructor_call(func, arg): # if '0.9' in utils.xml_generator: # return False call_invocation = declarations.call_invocation diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index 6df8374b..dc4f69cd 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -259,7 +259,8 @@ def endElement(self, name): if name in self.deep_declarations: self.__inst = None - def __read_location(self, decl, attrs): + @staticmethod + def __read_location(decl, attrs): to_skip = [] if "CastXML" in utils.xml_generator: @@ -294,13 +295,16 @@ def __update_membership(self, attrs): self.__members[parent] = [] self.__members[parent].append(attrs[XML_AN_ID]) - def __read_members(self, decl, attrs): + @staticmethod + def __read_members(decl, attrs): decl.declarations = attrs.get(XML_AN_MEMBERS, "") - def __read_bases(self, decl, attrs): + @staticmethod + def __read_bases(decl, attrs): decl.bases = attrs.get(XML_AN_BASES, "") - def __read_artificial(self, decl, attrs): + @staticmethod + def __read_artificial(decl, attrs): decl.is_artificial = attrs.get(XML_AN_ARTIFICIAL, False) def __read_mangled(self, decl, attrs): @@ -311,10 +315,12 @@ def __read_mangled(self, decl, attrs): mangled = mangled[:self.__mangled_suffix_len] decl.mangled = mangled - def __read_demangled(self, decl, attrs): + @staticmethod + def __read_demangled(decl, attrs): decl.demangled = attrs.get(XML_AN_DEMANGLED) - def __read_attributes(self, decl, attrs): + @staticmethod + def __read_attributes(decl, attrs): decl.attributes = attrs.get(XML_AN_ATTRIBUTES) def __read_access(self, attrs): @@ -323,19 +329,22 @@ def __read_access(self, attrs): XML_AN_ACCESS, declarations.ACCESS_TYPES.PUBLIC) - def __read_byte_size(self, decl, attrs): + @staticmethod + def __read_byte_size(decl, attrs): """Using duck typing to set the size instead of in constructor""" size = attrs.get(XML_AN_SIZE, 0) # Make sure the size is in bytes instead of bits decl.byte_size = int(size) / 8 - def __read_byte_offset(self, decl, attrs): + @staticmethod + def __read_byte_offset(decl, attrs): """Using duck typing to set the offset instead of in constructor""" offset = attrs.get(XML_AN_OFFSET, 0) # Make sure the size is in bytes instead of bits decl.byte_offset = int(offset) / 8 - def __read_byte_align(self, decl, attrs): + @staticmethod + def __read_byte_align(decl, attrs): """Using duck typing to set the alignment""" align = attrs.get(XML_AN_ALIGN, 0) # Make sure the size is in bytes instead of bits @@ -344,7 +353,8 @@ def __read_byte_align(self, decl, attrs): def __read_root(self, attrs): pass - def __read_file(self, attrs): + @staticmethod + def __read_file(attrs): return attrs.get(XML_AN_NAME, '') def __read_namespace(self, attrs): @@ -373,7 +383,8 @@ def __read_enumeration_value(self, attrs): num = int(attrs[XML_AN_INIT]) self.__inst.append_value(name, num) - def __guess_int_value(self, value_as_str): + @staticmethod + def __guess_int_value(value_as_str): # returns instance of int or None # if gcc compiled the code, than it is correct! numeric_suffix_letters = 'UuLlFf' @@ -399,7 +410,8 @@ def __read_array_type(self, attrs): # warnings.warn( msg ) return declarations.array_t(type_, size + 1) - def __read_cv_qualified_type(self, attrs): + @staticmethod + def __read_cv_qualified_type(attrs): if XML_AN_CONST in attrs and XML_AN_VOLATILE in attrs: return declarations.volatile_t( declarations.const_t(attrs[XML_AN_TYPE])) @@ -412,13 +424,16 @@ def __read_cv_qualified_type(self, attrs): else: assert 0 - def __read_pointer_type(self, attrs): + @staticmethod + def __read_pointer_type(attrs): return declarations.pointer_t(attrs[XML_AN_TYPE]) - def __read_reference_type(self, attrs): + @staticmethod + def __read_reference_type(attrs): return declarations.reference_t(attrs[XML_AN_TYPE]) - def __read_fundamental_type(self, attrs): + @staticmethod + def __read_fundamental_type(attrs): try: return declarations.FUNDAMENTAL_TYPES[attrs.get(XML_AN_NAME, '')] except KeyError: @@ -430,7 +445,8 @@ def __read_fundamental_type(self, attrs): # "pygccxml error: unable to find fundamental type with " + # "name '%s'.") % attrs.get( XML_AN_NAME, '' ) ) - def __read_offset_type(self, attrs): + @staticmethod + def __read_offset_type(attrs): base = attrs[XML_AN_BASE_TYPE] type_ = attrs[XML_AN_TYPE] if '0.9' in utils.xml_generator or 'CastXML' in utils.xml_generator: @@ -610,7 +626,8 @@ def __read_member_operator(self, attrs): operator.name = 'operator' + operator.name return operator - def __read_version(self, attrs): + @staticmethod + def __read_version(attrs): logger = utils.loggers.cxx_parser version_str = attrs.get(XML_AN_CVS_REVISION, 0.6) version = float(version_str) diff --git a/unittests/declarations_cache_tester.py b/unittests/declarations_cache_tester.py index e3535814..b7a1b71d 100644 --- a/unittests/declarations_cache_tester.py +++ b/unittests/declarations_cache_tester.py @@ -108,7 +108,8 @@ def test_cache_interface(self): cache = declarations_cache.file_cache_t(cache_file) self.assertTrue(len(cache._file_cache_t__cache) == 1) - def build_differing_cfg_list(self): + @staticmethod + def build_differing_cfg_list(): """ Return a list of configurations that all differ. """ cfg_list = [] def_cfg = xml_generator_configuration_t( diff --git a/unittests/file_cache_tester.py b/unittests/file_cache_tester.py index 1e592326..ec4d3c79 100644 --- a/unittests/file_cache_tester.py +++ b/unittests/file_cache_tester.py @@ -80,7 +80,8 @@ def test_from_file(self): ("cached declarations and source declarations are different, " + "after pickling")) - def test_reopen_cache(self): + @staticmethod + def test_reopen_cache(): """ Test opening cache files in a subprocess (with a clean environment). diff --git a/unittests/find_container_traits_tester.py b/unittests/find_container_traits_tester.py index bdff4b10..9257d4a1 100644 --- a/unittests/find_container_traits_tester.py +++ b/unittests/find_container_traits_tester.py @@ -170,7 +170,8 @@ def test_remove_defaults_partial_name_namespace(self): "key type string %r doesn't start with 'std::'" % key_type_string) - def test_from_ogre(self): + @staticmethod + def test_from_ogre(): x = ( 'map, ' + From 715361fed6ca7440c2ccbac9e77ac6407769c21a Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 26 Jun 2016 14:21:14 +0200 Subject: [PATCH 217/268] Imrove support for newer gccxml debian packages For backward compatibility, the debian packages wrapped CastXML inside the gccxml package. This means that if you call gccxml on ubunut 16.04 for example, what you get is CastXML ... this is a very weird decision. I can't support that hybrid package, because it will mess up pygccxml and a bunch of code would need to be added for this. People are now exlicitely asked to tell what they want to use: either they use the castxml package, which contains the CastXML binary, or they use the gccxml.real binary, which is provided by the gccxml package. --- CHANGELOG.md | 6 ++++++ pygccxml/parser/config.py | 4 ++++ pygccxml/parser/source_reader.py | 22 ++++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c480fddb..d0c1a4c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ Version 1.8.0 (not yet released) * find_xml_generator will now look for castxml first +* Do not allow to use the GCCXML provided by newer gccxml debian packages. + It is a wrapper around CastXML which can confuse pygccxml. + You should use the castxml package and the CastXML binary instead. + If you really want to use gccxml, the gccxml.real binary from the + gccxml debian package can still be used. + * ```declarations.is_string```, ```declarations.is_std_wstring```, ```declarations.is_std_ostream``` and ```declarations.is_std_wostream``` now correctly work when a the type is also a reference. diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index ee29ec9b..79844734 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -125,6 +125,10 @@ def xml_generator(self): @xml_generator.setter def xml_generator(self, xml_generator): """set xml_generator (gccxml or castxml)""" + if "real" in xml_generator: + # Support for gccxml.real from newer gccxml package + # Can be removed once gccxml support is dropped. + xml_generator = "gccxml" self.__xml_generator = xml_generator @property diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index c16bcbd9..d778cc5f 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -110,6 +110,28 @@ def __create_command_line(self, source_file, xml_file): """ if self.__config.xml_generator == "gccxml": + + # Check if the gccxml which is being used is not the gccxml + # package that exists in newer debian versions, and which is + # a wrapper around CastXML. I do not want to support this hybrid + # package because it can mislead pygccxml by applying patches + # for gccxml when in fact we are using CastXML. People can still + # use the gccxml.real binary from the gccxml package; or CastXML + # directly. + p = subprocess.Popen([self.__config.xml_generator_path], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + help = p.stdout.read().decode("utf-8") + p.stdout.close() + p.stderr.close() + if "CastXML wrapper" in help: + raise RuntimeError( + "You are using the gccxml debian package, which is a " + + "wrapper around CastXML. This is not allowed.\n" + + "Please use the gccxml.real binary from that package, " + "or use CastXML directly (which is recommended, as GCCXML " + "is now deprecated).") + return self.__create_command_line_gccxml(source_file, xml_file) elif self.__config.xml_generator == "castxml": return self.__create_command_line_castxml(source_file, xml_file) From 2aedcfa8706096b4f7d4ef231f0a4dd98f0f18ec Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 26 Jun 2016 14:38:09 +0200 Subject: [PATCH 218/268] Fix typo in error message --- pygccxml/parser/source_reader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index d778cc5f..0979bd75 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -319,7 +319,7 @@ def create_xml_file(self, source_file, destination=None): if self.__config.ignore_gccxml_output: if not os.path.isfile(xml_file): raise RuntimeError( - "Error occured while running " + + "Error occurred while running " + self.__config.xml_generator.upper() + ": %s status:%s" % (gccxml_msg, exit_status)) @@ -327,7 +327,7 @@ def create_xml_file(self, source_file, destination=None): if gccxml_msg or exit_status or not \ os.path.isfile(xml_file): raise RuntimeError( - "Error occured while running " + + "Error occurred while running " + self.__config.xml_generator.upper() + ": %s" % gccxml_msg) except Exception: From 3c705061ea3a029b188d2fc1c63b276ec60ed379 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Tue, 28 Jun 2016 19:32:43 +0200 Subject: [PATCH 219/268] Fix typos in error message --- pygccxml/utils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygccxml/utils/utils.py b/pygccxml/utils/utils.py index ee57ce73..3f4f86cf 100644 --- a/pygccxml/utils/utils.py +++ b/pygccxml/utils/utils.py @@ -157,7 +157,7 @@ def remove_file_no_raise(file_name, config): os.remove(file_name) except Exception as error: loggers.root.error( - "Error ocured while removing temprorary created file('%s'): %s" % + "Error occurred while removing temporary created file('%s'): %s" % (file_name, str(error))) From 4a5c391e8240bb76e896eeb3d5e82c8df8a5e049 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 30 Jun 2016 00:00:58 +0200 Subject: [PATCH 220/268] Try to find mingw on windows, improve handling of compilers (#57) - Improve algorithm which tries to guess the compiler path (for clang, gcc, msvc and mingw). - Update doc: a compiler path is now always guessed (for all platforms). Explain how to pass the compiler path. - Raise an exception if no compiler path is set --- pygccxml/parser/config.py | 43 ++++++++++++++++++++++++++++---- pygccxml/parser/source_reader.py | 11 +++++++- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/pygccxml/parser/config.py b/pygccxml/parser/config.py index 79844734..6a89961d 100644 --- a/pygccxml/parser/config.py +++ b/pygccxml/parser/config.py @@ -441,22 +441,55 @@ def create_compiler_path(xml_generator, compiler_path): """ Try to guess a path for the compiler. - Only needed with castxml on Mac or Linux. + If you want ot use a specific compiler, please provide the compiler + path manually, as the guess may not be what you are expecting. + Providing the path can be done by passing it as an argument (compiler_path) + to the xml_generator_configuration_t() or by defining it in your pygccxml + configuration file. """ if xml_generator == 'castxml' and compiler_path is None: - if platform.system() != 'Windows': - # On windows there is no need for the compiler path + if platform.system() == 'Windows': + # Look for msvc p = subprocess.Popen( - ['which', 'clang++'], stdout=subprocess.PIPE, + ['where', 'cl'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + compiler_path = p.stdout.read().decode("utf-8").rstrip() + p.stdout.close() + p.stderr.close() + # No mscv found; look for mingw + if compiler_path == '': + p = subprocess.Popen( + ['where', 'mingw'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + compiler_path = p.stdout.read().decode("utf-8").rstrip() + p.stdout.close() + p.stderr.close() + else: + # OS X or Linux + # Look for clang first, then gcc + p = subprocess.Popen( + ['which', 'clang++'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) compiler_path = p.stdout.read().decode("utf-8").rstrip() p.stdout.close() p.stderr.close() # No clang found; use gcc if compiler_path == '': - compiler_path = '/usr/bin/c++' + p = subprocess.Popen( + ['which', 'c++'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + compiler_path = p.stdout.read().decode("utf-8").rstrip() + p.stdout.close() + p.stderr.close() + + if compiler_path == "": + compiler_path = None return compiler_path diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 0979bd75..d2b53602 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -162,6 +162,15 @@ def __create_command_line_castxml(self, source_file, xmlfile): # Clang option: make sure clang knows we want to parse c++ cmd.append("-x c++") + # Always require a compiler path at this point + if self.__config.compiler_path is None: + raise( + RuntimeError, + "The compiler_path is not defined.\n" + "Please pass the compiler_path as argument to your " + "xml_generator_configuration_t(), or add it to your pygccxml " + "configuration file.") + # Platform specific options if platform.system() == 'Windows': @@ -172,7 +181,7 @@ def __create_command_line_castxml(self, source_file, xmlfile): cmd.append('--castxml-cc-gnu ' + self.__config.compiler_path) else: # We are using msvc - cmd.append('--castxml-cc-msvc cl') + cmd.append('--castxml-cc-msvc' + self.__config.compiler_path) if 'msvc9' == self.__config.compiler: cmd.append('-D"_HAS_TR1=0"') else: From 3df9cea579878eb52f6183185b2e77fe27ae1168 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 30 Jun 2016 07:40:56 +0200 Subject: [PATCH 221/268] Add missing space (#57) --- pygccxml/parser/source_reader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index d2b53602..14ad36e1 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -181,7 +181,7 @@ def __create_command_line_castxml(self, source_file, xmlfile): cmd.append('--castxml-cc-gnu ' + self.__config.compiler_path) else: # We are using msvc - cmd.append('--castxml-cc-msvc' + self.__config.compiler_path) + cmd.append('--castxml-cc-msvc ' + self.__config.compiler_path) if 'msvc9' == self.__config.compiler: cmd.append('-D"_HAS_TR1=0"') else: From 681ede7fc58cd090ab8040ee7015486558a6f213 Mon Sep 17 00:00:00 2001 From: Ethan Date: Thu, 30 Jun 2016 09:54:14 -0700 Subject: [PATCH 222/268] Quote path for Windows, fix muliline Exception --- pygccxml/parser/source_reader.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 14ad36e1..4ba709e3 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -164,12 +164,9 @@ def __create_command_line_castxml(self, source_file, xmlfile): # Always require a compiler path at this point if self.__config.compiler_path is None: - raise( - RuntimeError, - "The compiler_path is not defined.\n" - "Please pass the compiler_path as argument to your " - "xml_generator_configuration_t(), or add it to your pygccxml " - "configuration file.") + raise(RuntimeError("""Please pass the compiler_path as argument to + your xml_generator_configuration_t(), or add it to your pygccxml + configuration file.""")) # Platform specific options if platform.system() == 'Windows': @@ -181,7 +178,7 @@ def __create_command_line_castxml(self, source_file, xmlfile): cmd.append('--castxml-cc-gnu ' + self.__config.compiler_path) else: # We are using msvc - cmd.append('--castxml-cc-msvc ' + self.__config.compiler_path) + cmd.append('--castxml-cc-msvc ' + '"%s"' % self.__config.compiler_path) if 'msvc9' == self.__config.compiler: cmd.append('-D"_HAS_TR1=0"') else: From 40f37491c6e70171d43fdf508140caa14a72f13d Mon Sep 17 00:00:00 2001 From: Ethan Date: Thu, 30 Jun 2016 10:02:54 -0700 Subject: [PATCH 223/268] Give exit code if we don't have gccxml messages --- pygccxml/parser/source_reader.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 4ba709e3..b3f77569 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -332,10 +332,15 @@ def create_xml_file(self, source_file, destination=None): else: if gccxml_msg or exit_status or not \ os.path.isfile(xml_file): - raise RuntimeError( - "Error occurred while running " + - self.__config.xml_generator.upper() + ": %s" % - gccxml_msg) + if gccxml_msg or exit_status: + raise RuntimeError( + "Error occurred while running " + + self.__config.xml_generator.upper() + ": %s status:%s" % + (gccxml_msg, exit_status)) + else: + raise RuntimeError( + "Error occurred while running " + + self.__config.xml_generator.upper() + " xml file does not exist") except Exception: utils.remove_file_no_raise(xml_file, self.__config) raise From 3a35fc87d23ff347b8d3b3c2c9cbd691cdc49e45 Mon Sep 17 00:00:00 2001 From: Ethan Date: Thu, 30 Jun 2016 10:07:10 -0700 Subject: [PATCH 224/268] re-order exceptions; no file takes precedence --- pygccxml/parser/source_reader.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index b3f77569..0ef38ac6 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -332,15 +332,15 @@ def create_xml_file(self, source_file, destination=None): else: if gccxml_msg or exit_status or not \ os.path.isfile(xml_file): - if gccxml_msg or exit_status: + if not os.path.isfile(xml_file): raise RuntimeError( "Error occurred while running " + - self.__config.xml_generator.upper() + ": %s status:%s" % - (gccxml_msg, exit_status)) + self.__config.xml_generator.upper() + " xml file does not exist") else: raise RuntimeError( "Error occurred while running " + - self.__config.xml_generator.upper() + " xml file does not exist") + self.__config.xml_generator.upper() + ": %s status:%s" % + (gccxml_msg, exit_status)) except Exception: utils.remove_file_no_raise(xml_file, self.__config) raise From fc7fbacb5ed0fc2f19773d1b485c5d973dab7d1b Mon Sep 17 00:00:00 2001 From: Ethan Date: Thu, 30 Jun 2016 10:52:44 -0700 Subject: [PATCH 225/268] fixes for pep8 --- pygccxml/parser/source_reader.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index 0ef38ac6..abf8c076 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -341,6 +341,7 @@ def create_xml_file(self, source_file, destination=None): "Error occurred while running " + self.__config.xml_generator.upper() + ": %s status:%s" % (gccxml_msg, exit_status)) + except Exception: utils.remove_file_no_raise(xml_file, self.__config) raise From b8669c5ab6a72cb136ebc816b1010c2189c47a7d Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 30 Jun 2016 20:55:39 +0200 Subject: [PATCH 226/268] pep8 fixes - Replace tabs through spaces - Remove trailing whitespace - Fix lines too long --- pygccxml/parser/source_reader.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/pygccxml/parser/source_reader.py b/pygccxml/parser/source_reader.py index abf8c076..78ad6df9 100644 --- a/pygccxml/parser/source_reader.py +++ b/pygccxml/parser/source_reader.py @@ -164,9 +164,10 @@ def __create_command_line_castxml(self, source_file, xmlfile): # Always require a compiler path at this point if self.__config.compiler_path is None: - raise(RuntimeError("""Please pass the compiler_path as argument to - your xml_generator_configuration_t(), or add it to your pygccxml - configuration file.""")) + raise(RuntimeError( + "Please pass the compiler_path as argument to " + + "your xml_generator_configuration_t(), or add it to your " + + "pygccxml configuration file.")) # Platform specific options if platform.system() == 'Windows': @@ -178,7 +179,8 @@ def __create_command_line_castxml(self, source_file, xmlfile): cmd.append('--castxml-cc-gnu ' + self.__config.compiler_path) else: # We are using msvc - cmd.append('--castxml-cc-msvc ' + '"%s"' % self.__config.compiler_path) + cmd.append('--castxml-cc-msvc ' + + '"%s"' % self.__config.compiler_path) if 'msvc9' == self.__config.compiler: cmd.append('-D"_HAS_TR1=0"') else: @@ -335,13 +337,14 @@ def create_xml_file(self, source_file, destination=None): if not os.path.isfile(xml_file): raise RuntimeError( "Error occurred while running " + - self.__config.xml_generator.upper() + " xml file does not exist") + self.__config.xml_generator.upper() + + " xml file does not exist") else: raise RuntimeError( "Error occurred while running " + - self.__config.xml_generator.upper() + ": %s status:%s" % - (gccxml_msg, exit_status)) - + self.__config.xml_generator.upper() + + ": %s status:%s" % (gccxml_msg, exit_status)) + except Exception: utils.remove_file_no_raise(xml_file, self.__config) raise From e89c39ec1b791af35dcf8fc07d11b540b450e61c Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 3 Jul 2016 19:15:35 +0200 Subject: [PATCH 227/268] Performance: cache comparison data (#56) When an huge amount of declarations are compared (for example when calling sort() on the declaration tree), caching the data used in the __lt__() method used for comparison is hugely speeding up pygccxml. --- pygccxml/declarations/declaration.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/pygccxml/declarations/declaration.py b/pygccxml/declarations/declaration.py index db07c728..3ca3b7d6 100644 --- a/pygccxml/declarations/declaration.py +++ b/pygccxml/declarations/declaration.py @@ -40,6 +40,7 @@ def __init__( self._compiler = None self._partial_name = None self._decorated_name = None + self._cmp_data = None def __str__(self): """ @@ -91,14 +92,16 @@ def _get__cmp__data(self): Implementation detail. """ + if self._cmp_data is None: + # Cache self.cmp_data, because it is expensive to generate + # it each time + self._cmp_data = [ + declaration_utils.declaration_path(self.parent), + self.name, + self.location] + self._cmp_data.extend(self._get__cmp__items()) - data = [ - declaration_utils.declaration_path(self.parent), - self.name, - self.location] - data.extend(self._get__cmp__items()) - - return data + return self._cmp_data def __eq__(self, other): """ From 7030d450af9f5a46000473452c79f24fb0735c4a Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 3 Jul 2016 20:51:49 +0200 Subject: [PATCH 228/268] Cache the comparison data using the algorithms cache (#56) When the name changes, the cache needs to be reset. Also, the caching is done there (which I was not aware of first), so it is the logical place for this implementation. --- pygccxml/declarations/algorithms_cache.py | 15 +++++++++++++++ pygccxml/declarations/declaration.py | 12 +++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/pygccxml/declarations/algorithms_cache.py b/pygccxml/declarations/algorithms_cache.py index 6466f244..62ab9f29 100644 --- a/pygccxml/declarations/algorithms_cache.py +++ b/pygccxml/declarations/algorithms_cache.py @@ -24,6 +24,7 @@ def __init__(self): self._partial_declaration_path = None self._container_key_type = None self._container_element_type = None + self._cmp_data = None def disable(self): self._enabled = False @@ -121,6 +122,18 @@ def container_key_type(self, ktype): ktype = None self._container_key_type = ktype + @property + def cmp_data(self): + """Data used for comparison between declarations.""" + return self._cmp_data + + @cmp_data.setter + def cmp_data(self, cmp_data): + """Data used for comparison between declarations.""" + if not self.enabled: + cmp_data = None + self._cmp_data = cmp_data + def reset(self): self.full_name = None self.full_partial_name = None @@ -131,6 +144,7 @@ def reset(self): self.partial_declaration_path = None self.container_key_type = None self.container_element_type = None + self.cmp_data = None def reset_name_based(self): self.full_name = None @@ -141,6 +155,7 @@ def reset_name_based(self): self.partial_declaration_path = None self.container_key_type = None self.container_element_type = None + self.cmp_data = None def reset_access_type(self): self.access_type = None diff --git a/pygccxml/declarations/declaration.py b/pygccxml/declarations/declaration.py index 3ca3b7d6..11f1d41e 100644 --- a/pygccxml/declarations/declaration.py +++ b/pygccxml/declarations/declaration.py @@ -40,7 +40,6 @@ def __init__( self._compiler = None self._partial_name = None self._decorated_name = None - self._cmp_data = None def __str__(self): """ @@ -92,16 +91,15 @@ def _get__cmp__data(self): Implementation detail. """ - if self._cmp_data is None: - # Cache self.cmp_data, because it is expensive to generate - # it each time - self._cmp_data = [ + if self._cache.cmp_data is None: + cmp_data = [ declaration_utils.declaration_path(self.parent), self.name, self.location] - self._cmp_data.extend(self._get__cmp__items()) + cmp_data.extend(self._get__cmp__items()) + self._cache.cmp_data = cmp_data - return self._cmp_data + return self._cache.cmp_data def __eq__(self, other): """ From 10829aa6bf6d06df6d6a6cf34af5544e31ddcfa2 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 3 Jul 2016 20:58:59 +0200 Subject: [PATCH 229/268] Use the algorithm cache for decl_name and partial_decl_name --- pygccxml/declarations/algorithms_cache.py | 24 +++++++++++++++++++++++ pygccxml/declarations/cpptypes.py | 18 ++++++----------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/pygccxml/declarations/algorithms_cache.py b/pygccxml/declarations/algorithms_cache.py index 62ab9f29..1347d0b1 100644 --- a/pygccxml/declarations/algorithms_cache.py +++ b/pygccxml/declarations/algorithms_cache.py @@ -175,6 +175,8 @@ def enable(): def __init__(self): object.__init__(self) self._remove_alias = None + self._decl_string = None + self._partial_decl_string = None @property def remove_alias(self): @@ -186,5 +188,27 @@ def remove_alias(self, remove_alias): remove_alias = None self._remove_alias = remove_alias + @property + def decl_string(self): + return self._decl_string + + @decl_string.setter + def decl_string(self, decl_string): + if not type_algs_cache_t.enabled: + decl_string = None + self._decl_string = decl_string + + @property + def partial_decl_string(self): + return self._partial_decl_string + + @partial_decl_string.setter + def partial_decl_string(self, partial_decl_string): + if not type_algs_cache_t.enabled: + partial_decl_string = None + self._partial_decl_string = partial_decl_string + def reset(self): self.remove_alias = None + self.decl_string = None + self.partial_decl_string = None diff --git a/pygccxml/declarations/cpptypes.py b/pygccxml/declarations/cpptypes.py index 72c7b9a0..e75923df 100644 --- a/pygccxml/declarations/cpptypes.py +++ b/pygccxml/declarations/cpptypes.py @@ -19,8 +19,6 @@ def __init__(self): self.cache = algorithms_cache.type_algs_cache_t() self._byte_size = 0 self._byte_align = 0 - self._decl_string = None - self._partial_decl_string = None def __str__(self): res = self.decl_string @@ -49,19 +47,15 @@ def build_decl_string(self, with_defaults=True): @property def decl_string(self): - if self._decl_string is None: - self._decl_string = self.build_decl_string() - return self._decl_string - else: - return self._decl_string + if self.cache.decl_string is None: + self.cache.decl_string = self.build_decl_string() + return self.cache.decl_string @property def partial_decl_string(self): - if self._partial_decl_string is None: - self._partial_decl_string = self.build_decl_string(False) - return self._partial_decl_string - else: - return self._partial_decl_string + if self.cache.partial_decl_string is None: + self.cache.partial_decl_string = self.build_decl_string(False) + return self.cache.partial_decl_string def _clone_impl(self): raise NotImplementedError() From 7b3f14e44b269f17a03739e37497ebbe7500397f Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 3 Jul 2016 23:44:37 +0200 Subject: [PATCH 230/268] Performance: remove _sorted_list method and sort directly (#56) The method was just calling sort() on the list. As the _sorted_list() method could be called thousands of times there was an overhead of using a method for this. Sorting directly the different lists allows to improve slightly the performance --- pygccxml/declarations/calldef.py | 10 ++--- pygccxml/declarations/class_declaration.py | 44 ++++++++++------------ pygccxml/declarations/declaration.py | 6 --- pygccxml/declarations/namespace.py | 2 +- pygccxml/declarations/scopedef.py | 11 +++--- 5 files changed, 29 insertions(+), 44 deletions(-) diff --git a/pygccxml/declarations/calldef.py b/pygccxml/declarations/calldef.py index 741202bb..7174abc9 100644 --- a/pygccxml/declarations/calldef.py +++ b/pygccxml/declarations/calldef.py @@ -228,7 +228,7 @@ def _get__cmp__items(self): self.return_type, self.has_extern, self.does_throw, - self._sorted_list(self.exceptions), + self.exceptions.sort(), self.demangled_name, self.has_inline] elif "CastXML" in utils.xml_generator: @@ -238,7 +238,7 @@ def _get__cmp__items(self): self.return_type, self.has_extern, self.does_throw, - self._sorted_list(self.exceptions), + self.exceptions.sort(), self.has_inline] items.extend(self._get__cmp__call_items()) return items @@ -252,8 +252,7 @@ def __eq__(self, other): and self.arguments == other.arguments \ and self.has_extern == other.has_extern \ and self.does_throw == other.does_throw \ - and self._sorted_list(self.exceptions) == \ - other._sorted_list(other.exceptions) \ + and self.exceptions.sort() == other.exceptions.sort() \ and self.demangled_name == other.demangled_name elif "CastXML" in utils.xml_generator: # Do not check for demangled name @@ -261,8 +260,7 @@ def __eq__(self, other): and self.arguments == other.arguments \ and self.has_extern == other.has_extern \ and self.does_throw == other.does_throw \ - and self._sorted_list(self.exceptions) == \ - other._sorted_list(other.exceptions) + and self.exceptions.sort() == other.exceptions.sort() def __hash__(self): if "GCC" in utils.xml_generator: diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 108ecb3d..9369099b 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -273,40 +273,34 @@ def __str__(self): def _get__cmp__scope_items(self): """implementation details""" return [self.class_type, - self._sorted_list( [declaration_utils.declaration_path(base.related_class) - for base in self.bases]), - self._sorted_list( + for base in self.bases].sort(), [declaration_utils.declaration_path(derive.related_class) - for derive in self.derived]), + for derive in self.derived].sort(), self.is_abstract, - self._sorted_list(self.public_members), - self._sorted_list(self.private_members), - self._sorted_list(self.protected_members)] + self.public_members.sort(), + self.private_members.sort(), + self.protected_members.sort()] def __eq__(self, other): if not scopedef.scopedef_t.__eq__(self, other): return False return self.class_type == other.class_type \ - and self._sorted_list( - [declaration_utils.declaration_path(base.related_class) - for base in self.bases]) \ - == other._sorted_list( - [declaration_utils.declaration_path(base.related_class) - for base in other.bases]) \ - and self._sorted_list( - [declaration_utils.declaration_path(derive.related_class) - for derive in self.derived]) \ - == other._sorted_list( - [declaration_utils.declaration_path(derive.related_class) - for derive in other.derived]) \ + and [declaration_utils.declaration_path(base.related_class) + for base in self.bases].sort() \ + == [declaration_utils.declaration_path(base.related_class) + for base in other.bases].sort() \ + and [declaration_utils.declaration_path(derive.related_class) + for derive in self.derived].sort() \ + == [declaration_utils.declaration_path(derive.related_class) + for derive in other.derived].sort() \ and self.is_abstract == other.is_abstract \ - and self._sorted_list(self.public_members) \ - == other._sorted_list(other.public_members) \ - and self._sorted_list(self.private_members) \ - == other._sorted_list(other.private_members) \ - and self._sorted_list(self.protected_members) \ - == self._sorted_list(other.protected_members) + and self.public_members.sort() \ + == other.public_members.sort() \ + and self.private_members.sort() \ + == other.private_members.sort() \ + and self.protected_members.sort() \ + == other.protected_members.sort() def __hash__(self): return hash(self.class_type) diff --git a/pygccxml/declarations/declaration.py b/pygccxml/declarations/declaration.py index 11f1d41e..746008d2 100644 --- a/pygccxml/declarations/declaration.py +++ b/pygccxml/declarations/declaration.py @@ -66,12 +66,6 @@ def __str__(self): return "%s [%s]" % (name, cls) - @staticmethod - def _sorted_list(some_list): - """implementation details""" - some_list.sort() - return some_list - def _get__cmp__items(self): """ Implementation detail. diff --git a/pygccxml/declarations/namespace.py b/pygccxml/declarations/namespace.py index bd42831c..7894f847 100644 --- a/pygccxml/declarations/namespace.py +++ b/pygccxml/declarations/namespace.py @@ -43,7 +43,7 @@ def _get__cmp__scope_items(self): """ - return [self._sorted_list(self.declarations)] + return [self.declarations.sort()] def _get_declarations_impl(self): return self._declarations diff --git a/pygccxml/declarations/scopedef.py b/pygccxml/declarations/scopedef.py index 05627bf3..e7d0a5a7 100644 --- a/pygccxml/declarations/scopedef.py +++ b/pygccxml/declarations/scopedef.py @@ -208,23 +208,22 @@ def _get__cmp__items(self): if self._optimized: # in this case we don't need to build class internal declarations # list - items.append(self._sorted_list(self._all_decls_not_recursive)) + items.append(self._all_decls_not_recursive.sort()) else: - items.append(self._sorted_list(self.declarations)) + items.append(self.declarations.sort()) items.extend(self._get__cmp__scope_items()) return items def __eq__(self, other): if not declaration.declaration_t.__eq__(self, other): return False - return self._sorted_list(self.declarations[:]) \ - == other._sorted_list(other.declarations[:]) + return self.declarations[:].sort() == other.declarations[:].sort() # self_decls = self._all_decls_not_recursive # if not self._optimized: - # self_decls = self._sorted_list(self.declarations[:]) + # self_decls = self.declarations[:].sort() # other_decls = other._all_decls_not_recursive[:] # if not other._optimized: - # other_decls = other._sorted_list(other.declarations[:]) + # other_decls = other.declarations[:].sort() # else: # return self_decls == other_decls From 93164e425de8250ada1cba7a2a44f8ac10bb34bb Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 3 Jul 2016 23:52:22 +0200 Subject: [PATCH 231/268] Pep8 cleanup --- pygccxml/declarations/class_declaration.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 9369099b..3245edc7 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -286,14 +286,14 @@ def __eq__(self, other): if not scopedef.scopedef_t.__eq__(self, other): return False return self.class_type == other.class_type \ - and [declaration_utils.declaration_path(base.related_class) - for base in self.bases].sort() \ - == [declaration_utils.declaration_path(base.related_class) - for base in other.bases].sort() \ - and [declaration_utils.declaration_path(derive.related_class) - for derive in self.derived].sort() \ - == [declaration_utils.declaration_path(derive.related_class) - for derive in other.derived].sort() \ + and [declaration_utils.declaration_path(base.related_class) for + base in self.bases].sort() \ + == [declaration_utils.declaration_path(base.related_class) for + base in other.bases].sort() \ + and [declaration_utils.declaration_path(derive.related_class) for + derive in self.derived].sort() \ + == [declaration_utils.declaration_path(derive.related_class) for + derive in other.derived].sort() \ and self.is_abstract == other.is_abstract \ and self.public_members.sort() \ == other.public_members.sort() \ From b2e61f981c2981e2c03749a0d97590c0e6f67c6e Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 3 Jul 2016 23:57:33 +0200 Subject: [PATCH 232/268] More pep8 cleanup --- pygccxml/declarations/class_declaration.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index 3245edc7..e1a2a40d 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -272,11 +272,12 @@ def __str__(self): def _get__cmp__scope_items(self): """implementation details""" - return [self.class_type, - [declaration_utils.declaration_path(base.related_class) - for base in self.bases].sort(), - [declaration_utils.declaration_path(derive.related_class) - for derive in self.derived].sort(), + return [ + self.class_type, + [declaration_utils.declaration_path(base.related_class) for + base in self.bases].sort(), + [declaration_utils.declaration_path(derive.related_class) for + derive in self.derived].sort(), self.is_abstract, self.public_members.sort(), self.private_members.sort(), From 0f467ae78adf406add292a02b03fad8e614e7e6f Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 4 Jul 2016 23:45:29 +0200 Subject: [PATCH 233/268] Performance: cache normalized names and full names (#56) --- pygccxml/declarations/algorithms_cache.py | 52 +++++++++++++++ .../declarations/declarations_matchers.py | 18 ++---- pygccxml/declarations/templates.py | 63 +++++++++++++++++++ 3 files changed, 121 insertions(+), 12 deletions(-) diff --git a/pygccxml/declarations/algorithms_cache.py b/pygccxml/declarations/algorithms_cache.py index 1347d0b1..4c8f95d2 100644 --- a/pygccxml/declarations/algorithms_cache.py +++ b/pygccxml/declarations/algorithms_cache.py @@ -25,6 +25,10 @@ def __init__(self): self._container_key_type = None self._container_element_type = None self._cmp_data = None + self._normalized_name = None + self._normalized_partial_name = None + self._normalized_full_name_true = None + self._normalized_full_name_false = None def disable(self): self._enabled = False @@ -122,6 +126,46 @@ def container_key_type(self, ktype): ktype = None self._container_key_type = ktype + @property + def normalized_name(self): + return self._normalized_name + + @normalized_name.setter + def normalized_name(self, normalized_name): + if not self.enabled: + normalized_name = None + self._normalized_name = normalized_name + + @property + def normalized_partial_name(self): + return self._normalized_partial_name + + @normalized_partial_name.setter + def normalized_partial_name(self, normalized_partial_name): + if not self.enabled: + normalized_partial_name = None + self._normalized_partial_name = normalized_partial_name + + @property + def normalized_full_name_true(self): + return self._normalized_full_name_true + + @normalized_full_name_true.setter + def normalized_full_name_true(self, normalized_full_name_true): + if not self.enabled: + normalized_full_name_true = None + self._normalized_full_name_true = normalized_full_name_true + + @property + def normalized_full_name_false(self): + return self._normalized_full_name_false + + @normalized_full_name_false.setter + def normalized_full_name_false(self, normalized_full_name_false): + if not self.enabled: + normalized_full_name_false = None + self._normalized_full_name_false = normalized_full_name_false + @property def cmp_data(self): """Data used for comparison between declarations.""" @@ -145,6 +189,10 @@ def reset(self): self.container_key_type = None self.container_element_type = None self.cmp_data = None + self.normalized_name = None + self.normalized_partial_name = None + self.normalized_full_name_true = None + self.normalized_full_name_false = None def reset_name_based(self): self.full_name = None @@ -156,6 +204,10 @@ def reset_name_based(self): self.container_key_type = None self.container_element_type = None self.cmp_data = None + self.normalized_name = None + self.normalized_partial_name = None + self.normalized_full_name_true = None + self.normalized_full_name_false = None def reset_access_type(self): self.access_type = None diff --git a/pygccxml/declarations/declarations_matchers.py b/pygccxml/declarations/declarations_matchers.py index 8a2015ba..89aa39dc 100644 --- a/pygccxml/declarations/declarations_matchers.py +++ b/pygccxml/declarations/declarations_matchers.py @@ -156,26 +156,20 @@ def check_name(self, decl): assert self.name is not None if self.__opt_is_tmpl_inst: if not self.__opt_is_full_name: - if self.name != templates.normalize(decl.name) \ - and self.name != templates.normalize(decl.partial_name): + if self.name != templates.normalize_name(decl) \ + and self.name != templates.normalize_partial_name(decl): return False else: - if self.name != templates.normalize( - declaration_utils.full_name( - decl, with_defaults=True)) \ - and self.name != templates.normalize( - declaration_utils.full_name( - decl, with_defaults=False)): + if self.name != templates.normalize_full_name_true(decl) and \ + self.name != templates.normalize_full_name_false(decl): return False else: if not self.__opt_is_full_name: if self.name != decl.name and self.name != decl.partial_name: return False else: - if self.name != declaration_utils.full_name( - decl, with_defaults=True) \ - and self.name != declaration_utils.full_name( - decl, with_defaults=False): + if self.name != templates.normalize_full_name_true(decl) and \ + self.name != templates.normalize_full_name_false(decl): return False return True diff --git a/pygccxml/declarations/templates.py b/pygccxml/declarations/templates.py index 9b6c7427..9d2517aa 100644 --- a/pygccxml/declarations/templates.py +++ b/pygccxml/declarations/templates.py @@ -17,6 +17,7 @@ """ from . import pattern_parser +from . import declaration_utils __THE_PARSER = pattern_parser.parser_t('<', '>', ',') @@ -75,3 +76,65 @@ def normalize(decl_string): which are actually same: x::y< z > and x::y """ return __THE_PARSER.normalize(decl_string) + + +def normalize_name(decl): + """ + Cached variant of normalize + + Args: + decl (declaration.declaration_t): the declaration + + Returns: + str: normalized name + """ + if decl.cache.normalized_name is None: + decl.cache.normalized_name = normalize(decl.name) + return decl.cache.normalized_name + + +def normalize_partial_name(decl): + """ + Cached variant of normalize + + Args: + decl (declaration.declaration_t): the declaration + + Returns: + str: normalized name + """ + if decl.cache.normalized_partial_name is None: + decl.cache.normalized_partial_name = normalize(decl.partial_name) + return decl.cache.normalized_partial_name + + +def normalize_full_name_true(decl): + """ + Cached variant of normalize + + Args: + decl (declaration.declaration_t): the declaration + + Returns: + str: normalized name + """ + if decl.cache.normalized_full_name_true is None: + decl.cache.normalized_full_name_true = normalize( + declaration_utils.full_name(decl, with_defaults=True)) + return decl.cache.normalized_full_name_true + + +def normalize_full_name_false(decl): + """ + Cached variant of normalize + + Args: + decl (declaration.declaration_t): the declaration + + Returns: + str: normalized name + """ + if decl.cache.normalized_full_name_false is None: + decl.cache.normalized_full_name_false = normalize( + declaration_utils.full_name(decl, with_defaults=False)) + return decl.cache.normalized_full_name_false From 662cbd37b403acac23cb7f5daa3269f8dd590f7b Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Thu, 30 Jun 2016 14:06:29 -0600 Subject: [PATCH 234/268] Separate `scanner_t.__read_location` functions for gccxml and castxml Instead of deciding at runtime whether we're using gccxml or castxml, and have `scanner_t.__read_location` behave differently, monkey patch the fuction on first invocation to either `scanner_t.__read_location_gccxml` or `scanner_t.__read_location_castxml` depending on the xml generator we're using. Subsequent calls will then be directed to the appropriate handler. Change-Id: I25f7fdc54fcf6fd38af03ca4c16a0daf2182ae57 --- pygccxml/parser/scanner.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/pygccxml/parser/scanner.py b/pygccxml/parser/scanner.py index dc4f69cd..6f22c334 100644 --- a/pygccxml/parser/scanner.py +++ b/pygccxml/parser/scanner.py @@ -154,6 +154,11 @@ def __init__(self, xml_file, decl_factory, config, *args): self.__mangled_suffix = ' *INTERNAL* ' self.__mangled_suffix_len = len(self.__mangled_suffix) + self.__name_attrs_to_skip = [] + self.__read_location = \ + lambda decl, attrs, to_skip: self.__read_location_bootstrap( + self, decl, attrs, to_skip) + def read(self): xml.sax.parse(self.xml_file, self) @@ -223,7 +228,7 @@ def startElement(self, name, attrs): self.__update_membership(attrs) self.__declarations[element_id] = obj if not isinstance(obj, declarations.namespace_t): - self.__read_location(obj, attrs) + self.__read_location(obj, attrs, self.__name_attrs_to_skip) if isinstance(obj, declarations.class_t): self.__read_bases(obj, attrs) if isinstance(obj, declarations.typedef_t): @@ -260,16 +265,19 @@ def endElement(self, name): self.__inst = None @staticmethod - def __read_location(decl, attrs): + def __read_location_bootstrap(inst, decl, attrs, to_skip): + """ This function monkey patches the __read_location function to either + __read_location_gccxml or __read_location_castxml depending on the + xml generator in use + """ - to_skip = [] if "CastXML" in utils.xml_generator: # These fields are generated by clang, and have no location. # Just set an empty location for them. Gccxml does not have # this problem. # bug #19: gp_offset, fp_offset, overflow_arg_area, reg_save_area # bug #32: isa, flags, str and length were added in llvm 3.9 - to_skip = [ + inst.__name_attrs_to_skip = [ "gp_offset", "fp_offset", "overflow_arg_area", @@ -279,7 +287,19 @@ def __read_location(decl, attrs): "str", "length" ] + inst.__read_location = inst.__read_location_castxml + else: + inst.__read_location = inst.__read_location_gccxml + return inst.__read_location(decl, attrs, inst.__name_attrs_to_skip) + @staticmethod + def __read_location_gccxml(decl, attrs, to_skip): + decl.location = declarations.location_t( + file_name=attrs[XML_AN_FILE], + line=int(attrs[XML_AN_LINE])) + + @staticmethod + def __read_location_castxml(decl, attrs, to_skip): if "name" in attrs and attrs["name"] in to_skip: decl.location = declarations.location_t('', -1) else: From 1e8878ba0d40ffd08e9a3ee6af92afec3623a169 Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan Date: Wed, 29 Jun 2016 17:32:45 -0600 Subject: [PATCH 235/268] Cache `algorithm.declaration_path` result on first invocation `hierarchy_info_t` makes repeated calls to `algorithm.declaration_path` which affects performance. Added property `declaration_path` to `hierarchy_info_t` which will cache the result of a call to `algorithm.declaration_path` the first time the function is called. Added `hierarchy_info_t.declaration_path_hash` which maintains a hash of `hierarchy_info_t.declaration_path` for faster equality comparisons. Change-Id: Ibb45f71eb415e9ab9458d9e29a812111b3fb0ff9 --- pygccxml/declarations/class_declaration.py | 38 ++++++++++++++-------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/pygccxml/declarations/class_declaration.py b/pygccxml/declarations/class_declaration.py index e1a2a40d..d2be3503 100644 --- a/pygccxml/declarations/class_declaration.py +++ b/pygccxml/declarations/class_declaration.py @@ -67,17 +67,20 @@ def __init__(self, related_class=None, access=None, is_virtual=False): assert(access in ACCESS_TYPES.ALL) self._access = access self._is_virtual = is_virtual + self._declaration_path = None + self._declaration_path_hash = None def __eq__(self, other): if not isinstance(other, hierarchy_info_t): return False - return declaration_utils.declaration_path(self.related_class) == \ - declaration_utils.declaration_path(other.related_class) \ - and self.access == other.access \ - and self.is_virtual == other.is_virtual + return (self.declaration_path_hash == + other.declaration_path_hash) \ + and self._declaration_path == other._declaration_path \ + and self._access == other._access \ + and self._is_virtual == other._is_virtual def __hash__(self): - return hash(declaration_utils.declaration_path(self.related_class)) + return self.declaration_path_hash def __ne__(self, other): return not self.__eq__(other) @@ -85,14 +88,8 @@ def __ne__(self, other): def __lt__(self, other): if not isinstance(other, self.__class__): return self.__class__.__name__ < other.__class__.__name__ - return ( - declaration_utils.declaration_path(self.related_class), - self.access, - self.is_virtual) < ( - declaration_utils.declaration_path( - other.related_class), - other.access, - self.is_virtual) + return (self.declaration_path, self.access, self.is_virtual) < \ + (other.declaration_path, other.access, other.is_virtual) @property def related_class(self): @@ -104,6 +101,8 @@ def related_class(self, new_related_class): if new_related_class: assert(isinstance(new_related_class, class_t)) self._related_class = new_related_class + self._declaration_path = None + self._declaration_path_hash = None @property def access(self): @@ -135,6 +134,19 @@ def is_virtual(self): def is_virtual(self, new_is_virtual): self._is_virtual = new_is_virtual + @property + def declaration_path(self): + if self._declaration_path is None: + self._declaration_path = declaration_utils.declaration_path( + self.related_class) + return self._declaration_path + + @property + def declaration_path_hash(self): + if self._declaration_path_hash is None: + self._declaration_path_hash = hash(tuple(self.declaration_path)) + return self._declaration_path_hash + class class_declaration_t(declaration.declaration_t): From 648e8da38fa12004f0c83f6e1532349296425702 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 6 Jul 2016 00:06:57 +0200 Subject: [PATCH 236/268] Performance: do not check for string in patter_parser (#56) We can trust that the input is a string. Checking for this is expensive. The number of calls to is_str went down from 280000 calls to 22000 in most simple cases. The test is also no more needed. If somebody gives a wrong input, it will just fail with an exception. --- pygccxml/declarations/pattern_parser.py | 2 - unittests/data/basic.hpp | 14 ------- unittests/from_future_import_tester.py | 51 ------------------------- unittests/test_all.py | 2 - 4 files changed, 69 deletions(-) delete mode 100644 unittests/data/basic.hpp delete mode 100644 unittests/from_future_import_tester.py diff --git a/pygccxml/declarations/pattern_parser.py b/pygccxml/declarations/pattern_parser.py index 81acdd27..0ede4e98 100644 --- a/pygccxml/declarations/pattern_parser.py +++ b/pygccxml/declarations/pattern_parser.py @@ -28,7 +28,6 @@ def __init__( def has_pattern(self, decl_string): """implementation details""" - assert utils.is_str(decl_string) last_part = decl_string.split('::')[-1] return ( -1 != decl_string.find(self.__begin) and - @@ -37,7 +36,6 @@ def has_pattern(self, decl_string): def name(self, decl_string): """implementation details""" - assert utils.is_str(decl_string) if not self.has_pattern(decl_string): return decl_string args_begin = decl_string.find(self.__begin) diff --git a/unittests/data/basic.hpp b/unittests/data/basic.hpp deleted file mode 100644 index e2a90793..00000000 --- a/unittests/data/basic.hpp +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2014-2016 Insight Software Consortium. -// Copyright 2004-2009 Roman Yakovenko. -// Distributed under the Boost Software License, Version 1.0. -// See http://www.boost.org/LICENSE_1_0.txt - - -#include -using namespace std; - -namespace test -{ - int a = 10; -} - diff --git a/unittests/from_future_import_tester.py b/unittests/from_future_import_tester.py deleted file mode 100644 index db2afb9d..00000000 --- a/unittests/from_future_import_tester.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2014-2016 Insight Software Consortium. -# Copyright 2004-2008 Roman Yakovenko. -# Distributed under the Boost Software License, Version 1.0. -# See http://www.boost.org/LICENSE_1_0.txt - -from __future__ import unicode_literals - -import unittest -import parser_test_case -from pygccxml import declarations -from pygccxml import parser - - -class Test(parser_test_case.parser_test_case_t): - - """ - Some methods like namespace() verify if their argument is a string. - Check if this works well and if it is compatible with the - from __future__ import unicode_literals statement. - - """ - - def __init__(self, *args): - parser_test_case.parser_test_case_t.__init__(self, *args) - self.fname = "basic.hpp" - - def test_namespace_argument_string(self): - # Check with a string - self.global_ns.namespace("test") - - def test_namespace_argument_int(self): - # Check with an int, should raise an error - self.assertRaises(AssertionError, lambda: self.global_ns.namespace(1)) - - def setUp(self): - reader = parser.source_reader_t(self.config) - decls = reader.read_file(self.fname) - self.global_ns = declarations.get_global_namespace(decls) - - -def create_suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Test)) - return suite - - -def run_suite(): - unittest.TextTestRunner(verbosity=2).run(create_suite()) - -if __name__ == "__main__": - run_suite() diff --git a/unittests/test_all.py b/unittests/test_all.py index f3409da4..3b0220e8 100644 --- a/unittests/test_all.py +++ b/unittests/test_all.py @@ -62,7 +62,6 @@ import gccxml10185_tester import inline_specifier_tester import test_create_decl_string -import from_future_import_tester import pep8_tester import example_tester import test_utils @@ -128,7 +127,6 @@ gccxml10185_tester, inline_specifier_tester, test_create_decl_string, - from_future_import_tester, example_tester, test_utils, test_va_list_tag_removal, From d50a4790b5209eda26018045362b5999d44d5f91 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 11 Jul 2016 23:19:00 +0200 Subject: [PATCH 237/268] Fix is_my_case call Note that this method is not tested at all (but used by pypluplus). A proper unit test needs to be written --- pygccxml/declarations/other_traits.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygccxml/declarations/other_traits.py b/pygccxml/declarations/other_traits.py index 9a19041f..a7a3fd94 100644 --- a/pygccxml/declarations/other_traits.py +++ b/pygccxml/declarations/other_traits.py @@ -16,7 +16,7 @@ class internal_type_traits(object): # TODO: add exists function @staticmethod def get_by_name(type_, name): - if class_declaration_traits.class_traits.is_my_case(type_): + if class_declaration_traits.is_my_case(type_): cls = class_declaration_traits.class_traits.declaration_class( type_) return type_traits.remove_declarated( From d391925029d3aaa6e34c3a0d06f4bd73d7fa4f25 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 13 Jul 2016 21:39:30 +0200 Subject: [PATCH 238/268] Test is_smart_pointer methods --- unittests/data/test_smart_pointer.hpp | 15 +++++++ unittests/test_all.py | 4 +- unittests/test_smart_pointer.py | 64 +++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 unittests/data/test_smart_pointer.hpp create mode 100644 unittests/test_smart_pointer.py diff --git a/unittests/data/test_smart_pointer.hpp b/unittests/data/test_smart_pointer.hpp new file mode 100644 index 00000000..489aa6f9 --- /dev/null +++ b/unittests/data/test_smart_pointer.hpp @@ -0,0 +1,15 @@ +// Copyright 2014-2016 Insight Software Consortium. +// Copyright 2004-2009 Roman Yakovenko. +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +std::shared_ptr yes1(new int { 6 }); +std::auto_ptr yes2( new double { 7.0 } ); + +std::vector no1; +std::set< std::string > no2; diff --git a/unittests/test_all.py b/unittests/test_all.py index 3b0220e8..609035bd 100644 --- a/unittests/test_all.py +++ b/unittests/test_all.py @@ -71,6 +71,7 @@ import unnamed_classes_tester import test_map_gcc5 import test_argument_without_name +import test_smart_pointer testers = [ # , demangled_tester # failing right now @@ -134,7 +135,8 @@ test_cpp_standards, unnamed_classes_tester, test_map_gcc5, - test_argument_without_name + test_argument_without_name, + test_smart_pointer ] if 'posix' in os.name: diff --git a/unittests/test_smart_pointer.py b/unittests/test_smart_pointer.py new file mode 100644 index 00000000..0ffb1aa9 --- /dev/null +++ b/unittests/test_smart_pointer.py @@ -0,0 +1,64 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2009 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +import unittest +import parser_test_case + +from pygccxml import parser +from pygccxml import declarations + + +class Test(parser_test_case.parser_test_case_t): + + def __init__(self, *args): + parser_test_case.parser_test_case_t.__init__(self, *args) + self.header = "test_smart_pointer.hpp" + self.config.cflags = "-std=c++11" + + def test_other_traits(self): + """ + Test code in the other_traits module (is_smart_pointer methods). + + """ + + if self.config.xml_generator == "gccxml": + return + + decls = parser.parse([self.header], self.config) + global_ns = declarations.get_global_namespace(decls) + + criteria = declarations.declaration_matcher(name="yes1") + decls = declarations.matcher.find(criteria, global_ns) + self.assertTrue( + declarations.smart_pointer_traits.is_smart_pointer( + decls[0].decl_type)) + + criteria = declarations.declaration_matcher(name="yes2") + decls = declarations.matcher.find(criteria, global_ns) + self.assertTrue( + declarations.auto_ptr_traits.is_smart_pointer(decls[0].decl_type)) + + criteria = declarations.declaration_matcher(name="no1") + decls = declarations.matcher.find(criteria, global_ns) + self.assertFalse( + declarations.auto_ptr_traits.is_smart_pointer(decls[0].decl_type)) + + criteria = declarations.declaration_matcher(name="no2") + decls = declarations.matcher.find(criteria, global_ns) + self.assertFalse( + declarations.auto_ptr_traits.is_smart_pointer(decls[0].decl_type)) + + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(Test)) + return suite + + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run(create_suite()) + +if __name__ == "__main__": + run_suite() From bc97f0474cddae2435e042ba344f191dd9800eed Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 13 Jul 2016 21:42:25 +0200 Subject: [PATCH 239/268] Rename module to smart_pointer_traits It contains only smart pointer related code. --- pygccxml/declarations/__init__.py | 6 +++--- .../{other_traits.py => smart_pointer_traits.py} | 0 unittests/test_smart_pointer.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename pygccxml/declarations/{other_traits.py => smart_pointer_traits.py} (100%) diff --git a/pygccxml/declarations/__init__.py b/pygccxml/declarations/__init__.py index 050c2923..71774965 100644 --- a/pygccxml/declarations/__init__.py +++ b/pygccxml/declarations/__init__.py @@ -185,9 +185,9 @@ from .type_traits_classes import has_any_non_copyconstructor from .type_traits_classes import has_vtable -from .other_traits import auto_ptr_traits -from .other_traits import smart_pointer_traits -from .other_traits import internal_type_traits +from .smart_pointer_traits import auto_ptr_traits +from .smart_pointer_traits import smart_pointer_traits +from .smart_pointer_traits import internal_type_traits from .container_traits import list_traits from .container_traits import deque_traits diff --git a/pygccxml/declarations/other_traits.py b/pygccxml/declarations/smart_pointer_traits.py similarity index 100% rename from pygccxml/declarations/other_traits.py rename to pygccxml/declarations/smart_pointer_traits.py diff --git a/unittests/test_smart_pointer.py b/unittests/test_smart_pointer.py index 0ffb1aa9..91400c1d 100644 --- a/unittests/test_smart_pointer.py +++ b/unittests/test_smart_pointer.py @@ -19,7 +19,7 @@ def __init__(self, *args): def test_other_traits(self): """ - Test code in the other_traits module (is_smart_pointer methods). + Test code in the smart_pointer_traits module (is_smart_pointer methods). """ From 4ec574d0dfc59475818c995607cda75476e8940d Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 13 Jul 2016 21:53:28 +0200 Subject: [PATCH 240/268] Fix line to long in test --- unittests/test_smart_pointer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/test_smart_pointer.py b/unittests/test_smart_pointer.py index 91400c1d..df276512 100644 --- a/unittests/test_smart_pointer.py +++ b/unittests/test_smart_pointer.py @@ -19,7 +19,7 @@ def __init__(self, *args): def test_other_traits(self): """ - Test code in the smart_pointer_traits module (is_smart_pointer methods). + Test code in the smart_pointer_traits module. """ From ec8887cf2c571ed1e97f493bdbcd6bae66f44d46 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 13 Jul 2016 21:56:10 +0200 Subject: [PATCH 241/268] Log completion time for each test A test_cost.log file is generated each time all the tests are run. This allows to get an idea on how much time each test takes to complete. --- .gitignore | 1 + unittests/parser_test_case.py | 33 +++++++++++++++++++++++++++++++++ unittests/test_all.py | 5 +++++ 3 files changed, 39 insertions(+) diff --git a/.gitignore b/.gitignore index 5f868fc8..458bf903 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ pygccxml.egg-info *.prof .coverage* docs/examples/caching/example.hpp.xml +test_cost.log diff --git a/unittests/parser_test_case.py b/unittests/parser_test_case.py index 8b1b6d63..68b60b45 100644 --- a/unittests/parser_test_case.py +++ b/unittests/parser_test_case.py @@ -5,6 +5,7 @@ import pprint import sys +import time import unittest import autoconfig @@ -12,6 +13,7 @@ class parser_test_case_t(unittest.TestCase): CXX_PARSER_CFG = None + cost_file = None def __init__(self, *args): unittest.TestCase.__init__(self, *args) @@ -22,6 +24,37 @@ def __init__(self, *args): else: pass + def run(self, result=None): + """ + Override the run method. + + Allows to measure the time each test needs. The result is written + in the test_cost.log file. + + """ + start_time = time.time() + super(parser_test_case_t, self).run(result) + name = super(parser_test_case_t, self).id() + self.cost_file.write( + name + " " + + str(time.time() - start_time) + "\n") + + @classmethod + def setUpClass(cls): + """ + Open the cost file before the test. + + """ + cls.cost_file = open("test_cost.log", "a") + + @classmethod + def tearDownClass(cls): + """ + Close the cost file after the test. + + """ + cls.cost_file.close() + def _test_type_composition(self, type_, expected_compound, expected_base): self.assertTrue( isinstance(type_, expected_compound), diff --git a/unittests/test_all.py b/unittests/test_all.py index 609035bd..af1c0bf5 100644 --- a/unittests/test_all.py +++ b/unittests/test_all.py @@ -142,6 +142,11 @@ if 'posix' in os.name: testers.append(copy_constructor_tester) +if os.path.isfile("test_cost.log"): + # Remove the cost log file when tests are run again. + # See the parser_test_case which generates this file. + os.remove("test_cost.log") + def create_suite(): main_suite = unittest.TestSuite() From 7c89a5fb03e52a8a7953fe2592f17371d3a7ffff Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 13 Jul 2016 22:23:53 +0200 Subject: [PATCH 242/268] Make parser_test_case work with python 2.6 Mixing class and instance variables is not working with python 2.6 As the writing of one line is fast and we have around 250 test, we can open/close the file at each run. --- unittests/parser_test_case.py | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/unittests/parser_test_case.py b/unittests/parser_test_case.py index 68b60b45..3eed2c97 100644 --- a/unittests/parser_test_case.py +++ b/unittests/parser_test_case.py @@ -13,7 +13,6 @@ class parser_test_case_t(unittest.TestCase): CXX_PARSER_CFG = None - cost_file = None def __init__(self, *args): unittest.TestCase.__init__(self, *args) @@ -32,28 +31,13 @@ def run(self, result=None): in the test_cost.log file. """ - start_time = time.time() - super(parser_test_case_t, self).run(result) - name = super(parser_test_case_t, self).id() - self.cost_file.write( - name + " " + - str(time.time() - start_time) + "\n") - - @classmethod - def setUpClass(cls): - """ - Open the cost file before the test. - - """ - cls.cost_file = open("test_cost.log", "a") - - @classmethod - def tearDownClass(cls): - """ - Close the cost file after the test. - - """ - cls.cost_file.close() + with open("test_cost.log", "a") as cost_file: + start_time = time.time() + super(parser_test_case_t, self).run(result) + name = super(parser_test_case_t, self).id() + cost_file.write( + name + " " + + str(time.time() - start_time) + "\n") def _test_type_composition(self, type_, expected_compound, expected_base): self.assertTrue( From b41ccc179405d58bdec285e1304da43de1e90f81 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 13 Jul 2016 22:31:38 +0200 Subject: [PATCH 243/268] Use parser_test_case instead of normal TestCase This makes sure the tests run through the same testing pipeline as the other tests. --- unittests/call_invocation_tester.py | 3 ++- unittests/calling_convention_tester.py | 3 ++- unittests/declarations_cache_tester.py | 5 +++-- unittests/templates_tester.py | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/unittests/call_invocation_tester.py b/unittests/call_invocation_tester.py index 3177f998..add66a4d 100644 --- a/unittests/call_invocation_tester.py +++ b/unittests/call_invocation_tester.py @@ -4,10 +4,11 @@ # See http://www.boost.org/LICENSE_1_0.txt import unittest +import parser_test_case from pygccxml import declarations -class tester_t(unittest.TestCase): +class tester_t(parser_test_case.parser_test_case_t): def __test_split_impl(self, decl_string, name, args): self.assertTrue( diff --git a/unittests/calling_convention_tester.py b/unittests/calling_convention_tester.py index 23881e8b..c823009b 100644 --- a/unittests/calling_convention_tester.py +++ b/unittests/calling_convention_tester.py @@ -4,10 +4,11 @@ # See http://www.boost.org/LICENSE_1_0.txt import unittest +import parser_test_case from pygccxml import declarations -class Test(unittest.TestCase): +class Test(parser_test_case.parser_test_case_t): def test_extract(self): data = [ diff --git a/unittests/declarations_cache_tester.py b/unittests/declarations_cache_tester.py index b7a1b71d..8613d313 100644 --- a/unittests/declarations_cache_tester.py +++ b/unittests/declarations_cache_tester.py @@ -7,14 +7,15 @@ import unittest import os.path import autoconfig +import parser_test_case from pygccxml.parser.config import xml_generator_configuration_t from pygccxml.parser import declarations_cache -class decl_cache_tester(unittest.TestCase): +class decl_cache_tester(parser_test_case.parser_test_case_t): def __init__(self, *args): - unittest.TestCase.__init__(self, *args) + parser_test_case.parser_test_case_t.__init__(self, *args) if not os.path.exists(autoconfig.build_directory): os.makedirs(autoconfig.build_directory) diff --git a/unittests/templates_tester.py b/unittests/templates_tester.py index 60fc9703..4e40048b 100644 --- a/unittests/templates_tester.py +++ b/unittests/templates_tester.py @@ -4,11 +4,11 @@ # See http://www.boost.org/LICENSE_1_0.txt import unittest - +import parser_test_case from pygccxml import declarations -class Test(unittest.TestCase): +class Test(parser_test_case.parser_test_case_t): def __test_split_impl(self, decl_string, name, args): self.assertTrue( From f9f0deb554f4e2c574c3f72b1940ab9a915a41c7 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 13 Jul 2016 23:13:53 +0200 Subject: [PATCH 244/268] Rename test method --- unittests/test_smart_pointer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/test_smart_pointer.py b/unittests/test_smart_pointer.py index df276512..b0953678 100644 --- a/unittests/test_smart_pointer.py +++ b/unittests/test_smart_pointer.py @@ -17,7 +17,7 @@ def __init__(self, *args): self.header = "test_smart_pointer.hpp" self.config.cflags = "-std=c++11" - def test_other_traits(self): + def test_smart_pointer(self): """ Test code in the smart_pointer_traits module. From 3b3984b60946614426a2089f71f3f53f57bd62c2 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 24 Jul 2016 09:28:07 +0200 Subject: [PATCH 245/268] Demonstrate error in pattern parser (#60) The test is currently disabled and will be added to the test suite once the problem is fixed. --- unittests/data/test_pattern_parser.hpp | 17 ++++++++++ unittests/test_pattern_parser.py | 46 ++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 unittests/data/test_pattern_parser.hpp create mode 100644 unittests/test_pattern_parser.py diff --git a/unittests/data/test_pattern_parser.hpp b/unittests/data/test_pattern_parser.hpp new file mode 100644 index 00000000..55bd8ace --- /dev/null +++ b/unittests/data/test_pattern_parser.hpp @@ -0,0 +1,17 @@ +// Copyright 2014-2016 Insight Software Consortium. +// Copyright 2004-2009 Roman Yakovenko. +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +#include +using namespace std; + +template +class myClass {}; + +int main () { + myClass(const std::string &, const std::string &)> m; + return 0; +} + + diff --git a/unittests/test_pattern_parser.py b/unittests/test_pattern_parser.py new file mode 100644 index 00000000..7a4e1e78 --- /dev/null +++ b/unittests/test_pattern_parser.py @@ -0,0 +1,46 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2009 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +import unittest +import parser_test_case + +from pygccxml import parser +from pygccxml import declarations + + +class Test(parser_test_case.parser_test_case_t): + + def __init__(self, *args): + parser_test_case.parser_test_case_t.__init__(self, *args) + self.header = "test_pattern_parser.hpp" + self.config.cflags = "-std=c++11" + + def test_map_gcc5(self): + """ + Demonstrate error in pattern parser, see #60 + + """ + + if self.config.xml_generator == "gccxml": + return + + decls = parser.parse([self.header], self.config) + + for decl in declarations.make_flatten(decls): + if "myClass" in decl.name: + _ = decl.partial_name + + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(Test)) + return suite + + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run(create_suite()) + +if __name__ == "__main__": + run_suite() From 314e7e8e1af84cc39636c2823fda9b6447a1f424 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 25 Jul 2016 21:23:24 +0200 Subject: [PATCH 246/268] Include string to make gcc happy --- unittests/data/test_pattern_parser.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/unittests/data/test_pattern_parser.hpp b/unittests/data/test_pattern_parser.hpp index 55bd8ace..fbb901ef 100644 --- a/unittests/data/test_pattern_parser.hpp +++ b/unittests/data/test_pattern_parser.hpp @@ -3,6 +3,7 @@ // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt +#include #include using namespace std; From 9357732bf7ba6e7ac831b1ba1d06fd9d0b69a542 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 27 Jul 2016 23:12:54 +0200 Subject: [PATCH 247/268] Support arguments in templates definitions This fixes the problem found in #60 The parentheses blocks need to be taken care of separately. An extensive unit test has been written for the splitting method to make sure the expected result is returned. --- pygccxml/declarations/pattern_parser.py | 93 ++++++++++++++--- unittests/data/test_pattern_parser.hpp | 23 ++++- unittests/test_all.py | 4 +- unittests/test_pattern_parser.py | 128 +++++++++++++++++++++++- 4 files changed, 231 insertions(+), 17 deletions(-) diff --git a/pygccxml/declarations/pattern_parser.py b/pygccxml/declarations/pattern_parser.py index 0ede4e98..ecf2e07c 100644 --- a/pygccxml/declarations/pattern_parser.py +++ b/pygccxml/declarations/pattern_parser.py @@ -3,9 +3,12 @@ # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt -"""implementation details""" +""" +Implementation details -from .. import utils +""" + +import re class parser_t(object): @@ -27,7 +30,15 @@ def __init__( self.__escape = '\\' def has_pattern(self, decl_string): - """implementation details""" + """ + Implementation detail + + """ + if self.__begin == "<": + # Cleanup parentheses blocks before checking for the pattern + # See also the args() method (in this file) for more explanations. + decl_string = re.sub("\s\(.*?\)", "", decl_string).strip() + last_part = decl_string.split('::')[-1] return ( -1 != decl_string.find(self.__begin) and - @@ -59,30 +70,84 @@ def __find_args_separator(self, decl_string, start_pos): return -1 def args(self, decl_string): - """implementation details""" + """ + Extracts a list of arguments from the provided declaration string. + + Implementation detail. Example usages: + Input: myClass, std::vector> + Output: [std::vector, std::vector] + + Args: + decl_string (str): the full declaration string + + Returns: + list: list of arguments as strings + + """ args_begin = decl_string.find(self.__begin) args_end = decl_string.rfind(self.__end) if -1 in (args_begin, args_end) or args_begin == args_end: raise RuntimeError( - "%s doesn't valid template instantiation string" % + "%s doesn't validate template instantiation string" % decl_string) - args_only = decl_string[args_begin + 1: args_end] + args_only = decl_string[args_begin + 1: args_end].strip() + + # The list of arguments to be returned args = [] + + parentheses_blocks = [] + prev_span = 0 + if self.__begin == "<": + # In case where we are splitting template names, there + # can be parentheses blocks (for arguments) that need to be taken + # care of. + + # Build a regex matching a space (\s) + # + something inside parentheses + regex = re.compile("\s\(.*?\)") + for m in regex.finditer(args_only): + # Store the position and the content + parentheses_blocks.append([m.start() - prev_span, m.group()]) + prev_span = m.end() - m.start() + # Cleanup the args_only string by removing the parentheses and + # their content. + args_only = args_only.replace(m.group(), "") + + # Now we are trying to split the args_only string in multiple arguments previous_found, found = 0, 0 while True: found = self.__find_args_separator(args_only, previous_found) if -1 == found: - args.append(args_only[previous_found:]) + args.append(args_only[previous_found:].strip()) + # This is the last argument. Break out of the loop. break - # elif decl_string[ found ] == self.__end: - # print args - # raise RuntimeError( "unmatched '%s' token has been found." - # % self.__end ) else: - args.append(args_only[previous_found: found]) - previous_found = found + 1 # skip found sep - return [arg.strip() for arg in args] + args.append(args_only[previous_found: found].strip()) + previous_found = found + 1 # skip found separator + + # Get the size and position for each argument + absolute_pos_list = [] + absolute_pos = 0 + for arg in args: + absolute_pos += len(arg) + absolute_pos_list.append(absolute_pos) + + for item in parentheses_blocks: + # In case where there are parentheses blocks we add them back + # to the right argument + parentheses_block_absolute_pos = item[0] + parentheses_block_string = item[1] + + current_arg_absolute_pos = 0 + for arg_index, arg_absolute_pos in enumerate(absolute_pos_list): + current_arg_absolute_pos += arg_absolute_pos + if current_arg_absolute_pos >= parentheses_block_absolute_pos: + # Add the parentheses block back and break out of the loop. + args[arg_index] += parentheses_block_string + break + + return args NOT_FOUND = (-1, -1) """implementation details""" diff --git a/unittests/data/test_pattern_parser.hpp b/unittests/data/test_pattern_parser.hpp index fbb901ef..41dccf0f 100644 --- a/unittests/data/test_pattern_parser.hpp +++ b/unittests/data/test_pattern_parser.hpp @@ -10,8 +10,29 @@ using namespace std; template class myClass {}; +template +class myClass2 {}; + +template +class myClass3 {}; + int main () { - myClass(const std::string &, const std::string &)> m; + myClass(const std::string &, const std::string &)> m1; + + myClass(const int &, const int &)> m2; + + myClass2(const int &, const int &), std::vector> m3; + + myClass2, std::vector(const int &, const int &)> m4; + + myClass3, std::vector(const int &, const int &), std::vector(const int &, const int &)> m5; + + myClass3(const int &, const int &), std::vector, std::vector(const int &, const int &)> m6; + + myClass3(const int &, const int &), std::vector(const int &, const int &), std::vector> m7; + + myClass3(const int &, const int &), std::vector(double &)> m8; + return 0; } diff --git a/unittests/test_all.py b/unittests/test_all.py index af1c0bf5..21b05e8b 100644 --- a/unittests/test_all.py +++ b/unittests/test_all.py @@ -72,6 +72,7 @@ import test_map_gcc5 import test_argument_without_name import test_smart_pointer +import test_pattern_parser testers = [ # , demangled_tester # failing right now @@ -136,7 +137,8 @@ unnamed_classes_tester, test_map_gcc5, test_argument_without_name, - test_smart_pointer + test_smart_pointer, + test_pattern_parser ] if 'posix' in os.name: diff --git a/unittests/test_pattern_parser.py b/unittests/test_pattern_parser.py index 7a4e1e78..0ecb4092 100644 --- a/unittests/test_pattern_parser.py +++ b/unittests/test_pattern_parser.py @@ -17,7 +17,7 @@ def __init__(self, *args): self.header = "test_pattern_parser.hpp" self.config.cflags = "-std=c++11" - def test_map_gcc5(self): + def test_template_split_std_vector(self): """ Demonstrate error in pattern parser, see #60 @@ -32,6 +32,132 @@ def test_map_gcc5(self): if "myClass" in decl.name: _ = decl.partial_name + def test_matcher(self): + """ + Run the matcher on all the templated classes. + + This exercises the whole pipeline even more. + + """ + decls = parser.parse([self.header], self.config) + global_ns = declarations.get_global_namespace(decls) + criteria = declarations.declaration_matcher(name="myClass") + _ = declarations.matcher.find(criteria, global_ns) + + def test_split(self): + """ + Test a bunch of tricky name/args splits. More combinations could be + tested but this is already covering most of the cases. + + In test_template_split_std_vector we test for a specific case that + was failing (in a real world scenario). + Here we test more possible combinations to make sure the splitting + method is robust enough. + + """ + + p1 = "std::vector >" + p2 = "std::vector >" + args_list = [ + "const std::basic_string &", "const int &", "const double &"] + + for arg in args_list: + + l = [p1] + name, args = declarations.templates.split( + "myClass0a<" + ", ".join(l) + ">") + self.assertEqual(name, "myClass0a") + self.assertEqual(args, l) + + l = [p1, p2] + name, args = declarations.templates.split( + "myClass0b<" + ", ".join(l) + ">") + self.assertEqual(name, "myClass0b") + self.assertEqual(args, l) + + l = [p1, p2, p2] + name, args = declarations.templates.split( + "myClass0c<" + ", ".join(l) + ">") + self.assertEqual(name, "myClass0c") + self.assertEqual(args, l) + + l = [p1 + " (" + arg + ")"] + name, args = declarations.templates.split( + "myClass1<" + ", ".join(l) + ">") + self.assertEqual(name, "myClass1") + self.assertEqual(args, l) + + l = [p1 + " (" + arg + ", " + arg + ")"] + name, args = declarations.templates.split( + "myClass2<" + ", ".join(l) + ">") + self.assertEqual(name, "myClass2") + self.assertEqual(args, l) + + l = [p2 + " (" + arg + ", " + arg + ")"] + name, args = declarations.templates.split( + "myClass3<" + ", ".join(l) + ">") + self.assertEqual(name, "myClass3") + self.assertEqual(args, l) + + l = [p1 + " (" + arg + ", " + arg + ", " + arg + ")"] + name, args = declarations.templates.split( + "myClass4<" + ", ".join(l) + ">") + self.assertEqual(name, "myClass4") + self.assertEqual(args, l) + + l = [ + p1 + " (" + arg + ", " + arg + ", " + arg + ")", + p1] + name, args = declarations.templates.split( + "myClass5<" + ", ".join(l) + ">") + self.assertEqual(name, "myClass5") + self.assertEqual(args, l) + + l = [ + p1, + p1 + " (" + arg + ", " + arg + ", " + arg + ")"] + name, args = declarations.templates.split( + "myClass6<" + ", ".join(l) + ">") + self.assertEqual(name, "myClass6") + self.assertEqual(args, l) + + l = [ + p2 + " (" + arg + ")", + p1, + p1 + " (" + arg + ", " + arg + ", " + arg + ")"] + name, args = declarations.templates.split( + "myClass7<" + ", ".join(l) + ">") + self.assertEqual(name, "myClass7") + self.assertEqual(args, l) + + l = [ + p1, + p2 + " (" + arg + ")", + p1 + " (" + arg + ", " + arg + ", " + arg + ")"] + name, args = declarations.templates.split( + "myClass8<" + ", ".join(l) + ">") + self.assertEqual(name, "myClass8") + self.assertEqual(args, l) + + l = [ + p2 + " (" + arg + ")", + p1 + " (" + arg + ", " + arg + ")", + p1] + name, args = declarations.templates.split( + "myClass9<" + ", ".join(l) + ">") + self.assertEqual(name, "myClass9") + self.assertEqual(args, l) + + l = [ + p2 + " (" + arg + ")", + p1 + " (" + arg + ", " + arg + ", " + arg + ")", + p1, + p2] + name, args = declarations.templates.split( + "myClass10<" + ", ".join(l) + ">") + self.assertEqual(name, "myClass10") + self.assertEqual(args, l) + def create_suite(): suite = unittest.TestSuite() From 34defa86734ddb404e42ab0c2b3e7ef379cdb393 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 27 Jul 2016 23:18:30 +0200 Subject: [PATCH 248/268] Document fix in changelog (#60) --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0c1a4c0..f95a4e63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ Version 1.8.0 (not yet released) You should use the castxml package and the CastXML binary instead. If you really want to use gccxml, the gccxml.real binary from the gccxml debian package can still be used. + +* Fix parsing of boost/locale.hpp code. + Templated class instantiations with specializations are now better supported, + specifically when containing parentheses: + myClass(const std::string &, const std::string &)> obj; * ```declarations.is_string```, ```declarations.is_std_wstring```, ```declarations.is_std_ostream``` and ```declarations.is_std_wostream``` now From 332ceb1e352fe6c3629a03267cde1e635e803cb0 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 27 Jul 2016 23:27:40 +0200 Subject: [PATCH 249/268] Do not run the c++11 matcher test with gccxml --- unittests/test_pattern_parser.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/unittests/test_pattern_parser.py b/unittests/test_pattern_parser.py index 0ecb4092..ac4a7002 100644 --- a/unittests/test_pattern_parser.py +++ b/unittests/test_pattern_parser.py @@ -39,6 +39,10 @@ def test_matcher(self): This exercises the whole pipeline even more. """ + + if self.config.xml_generator == "gccxml": + return + decls = parser.parse([self.header], self.config) global_ns = declarations.get_global_namespace(decls) criteria = declarations.declaration_matcher(name="myClass") From 92b79b61e0396483a37c382b38e088b6c3899473 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 28 Jul 2016 23:51:11 +0200 Subject: [PATCH 250/268] Add missing licences. Keep the licence text the same for all the files, it makes it more maintainable --- unittests/data/test_copy_constructor.hpp | 1 + unittests/data/test_map_gcc5.hpp | 1 + unittests/data/type_as_exception_bug.h | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/unittests/data/test_copy_constructor.hpp b/unittests/data/test_copy_constructor.hpp index a891a5ed..878b0037 100644 --- a/unittests/data/test_copy_constructor.hpp +++ b/unittests/data/test_copy_constructor.hpp @@ -1,4 +1,5 @@ // Copyright 2014-2016 Insight Software Consortium. +// Copyright 2004-2009 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/test_map_gcc5.hpp b/unittests/data/test_map_gcc5.hpp index 2482848f..059f2443 100644 --- a/unittests/data/test_map_gcc5.hpp +++ b/unittests/data/test_map_gcc5.hpp @@ -1,4 +1,5 @@ // Copyright 2014-2016 Insight Software Consortium. +// Copyright 2004-2009 Roman Yakovenko. // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt diff --git a/unittests/data/type_as_exception_bug.h b/unittests/data/type_as_exception_bug.h index 36facd40..23739efd 100644 --- a/unittests/data/type_as_exception_bug.h +++ b/unittests/data/type_as_exception_bug.h @@ -1,3 +1,8 @@ +// Copyright 2014-2016 Insight Software Consortium. +// Copyright 2004-2009 Roman Yakovenko. +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + #ifndef __key_error_bug_h__ #define __key_error_bug_h__ From d9aaa34ad5dec438825083ad910a3baca544d816 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sat, 27 Aug 2016 18:21:05 +0200 Subject: [PATCH 251/268] Add example about nested types --- docs/examples.rst | 1 + docs/examples/nested-types/example.hpp | 8 ++++ docs/examples/nested-types/example.py | 66 ++++++++++++++++++++++++++ docs/examples/nested-types/example.rst | 17 +++++++ 4 files changed, 92 insertions(+) create mode 100644 docs/examples/nested-types/example.hpp create mode 100644 docs/examples/nested-types/example.py create mode 100644 docs/examples/nested-types/example.rst diff --git a/docs/examples.rst b/docs/examples.rst index 9c951ae2..2303fa07 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -15,5 +15,6 @@ First examples examples/searching/example.rst examples/equality/example.rst examples/functions/example.rst + examples/nested-types/example.rst examples/caching/example.rst examples/print-example/example.rst diff --git a/docs/examples/nested-types/example.hpp b/docs/examples/nested-types/example.hpp new file mode 100644 index 00000000..61793185 --- /dev/null +++ b/docs/examples/nested-types/example.hpp @@ -0,0 +1,8 @@ +// Copyright 2014-2016 Insight Software Consortium. +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +namespace ns{ + const int a = 0; + const volatile int *b = 0; +} diff --git a/docs/examples/nested-types/example.py b/docs/examples/nested-types/example.py new file mode 100644 index 00000000..38bdabb7 --- /dev/null +++ b/docs/examples/nested-types/example.py @@ -0,0 +1,66 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +from pygccxml import utils +from pygccxml import declarations +from pygccxml import parser + +import os +import sys +import warnings +warnings.simplefilter("error", Warning) +# Find out the file location within the sources tree +this_module_dir_path = os.path.abspath( + os.path.dirname(sys.modules[__name__].__file__)) + +# Find out the c++ parser +generator_path, generator_name = utils.find_xml_generator() + +# Configure the xml generator +xml_generator_config = parser.xml_generator_configuration_t( + xml_generator_path=generator_path, + xml_generator=generator_name) + +# The c++ file we want to parse +filename = "example.hpp" +filename = this_module_dir_path + "/" + filename + +decls = parser.parse([filename], xml_generator_config) +global_namespace = declarations.get_global_namespace(decls) +ns = global_namespace.namespace("ns") + +a = ns.variables()[0] + +print("My name is: " + a.name) +# > My name is: a + +print("My type is: " + str(a.decl_type)) +# > My type is: int const + +# If we print real python type: +print("My type is : " + str(type(a.decl_type))) +# > My type is: + +# Types are nested in pygccxml. This means that you will get information +# about the first type only. You can access the "base" type by removing +# the const part: +print("My base type is: " + str(type(declarations.remove_const(a.decl_type)))) +# > My base type is: + +# You use the is_const function to check for a type: +print("Is 'a' a const ?: " + str(declarations.is_const(a.decl_type))) +# > Is 'a' a const ?: True + +# A more complex example with variable b: +b = ns.variables()[1] +print("My type is: " + str(type(b.decl_type))) +# > My type is: +print("My type is: " + str(type( + declarations.remove_const( + declarations.remove_volatile( + declarations.remove_pointer(b.decl_type)))))) +# > My type is: + +# The declarations module contains much more methods allowing you to +# navigate the nested types list. diff --git a/docs/examples/nested-types/example.rst b/docs/examples/nested-types/example.rst new file mode 100644 index 00000000..f13d504a --- /dev/null +++ b/docs/examples/nested-types/example.rst @@ -0,0 +1,17 @@ +============ +Nested types +============ + +This example shows how to work with types. + +Let's consider the following c++ file: + +.. literalinclude:: example.hpp + :language: c++ + :lines: 4- + +The following code allows you to extract information about the types of variables: + +.. literalinclude:: example.py + :language: python + :lines: 5,6,7,16-26,28- From 7c3f60f1d9c68a413173a4f994799972ecb35e36 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 28 Aug 2016 22:18:50 +0200 Subject: [PATCH 252/268] Fix bug in remove_pointer function when used on a function pointer (#61) --- CHANGELOG.md | 3 + pygccxml/declarations/type_traits.py | 2 - unittests/data/test_function_pointer.hpp | 12 ++++ unittests/test_all.py | 4 +- unittests/test_function_pointer.py | 76 ++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 unittests/data/test_function_pointer.hpp create mode 100644 unittests/test_function_pointer.py diff --git a/CHANGELOG.md b/CHANGELOG.md index f95a4e63..22266531 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ Version 1.8.0 (not yet released) specifically when containing parentheses: myClass(const std::string &, const std::string &)> obj; +* When using the ```remove_pointer``` function on a function pointer, the + ```remove_pointer``` function now correctly returns a ```calldef_type_t```. + * ```declarations.is_string```, ```declarations.is_std_wstring```, ```declarations.is_std_ostream``` and ```declarations.is_std_wostream``` now correctly work when a the type is also a reference. diff --git a/pygccxml/declarations/type_traits.py b/pygccxml/declarations/type_traits.py index 11d3f28a..11541301 100644 --- a/pygccxml/declarations/type_traits.py +++ b/pygccxml/declarations/type_traits.py @@ -249,8 +249,6 @@ def remove_pointer(type_): return ( cpptypes.volatile_t(cpptypes.const_t(nake_type.base.base.base)) ) - elif isinstance(nake_type.base, cpptypes.calldef_type_t): - return type_ else: return nake_type.base diff --git a/unittests/data/test_function_pointer.hpp b/unittests/data/test_function_pointer.hpp new file mode 100644 index 00000000..bc248cab --- /dev/null +++ b/unittests/data/test_function_pointer.hpp @@ -0,0 +1,12 @@ +// Copyright 2014-2016 Insight Software Consortium. +// Copyright 2004-2009 Roman Yakovenko. +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// func1 is a function pointer +// In this case, func1 is the declaration of a function which has two arguments +// (on the right) and returns nothing (void on the left) +void (*func1)(int, double); + +// Another pointer, but not a function pointer +int const volatile* myPointer; \ No newline at end of file diff --git a/unittests/test_all.py b/unittests/test_all.py index 21b05e8b..2087e939 100644 --- a/unittests/test_all.py +++ b/unittests/test_all.py @@ -73,6 +73,7 @@ import test_argument_without_name import test_smart_pointer import test_pattern_parser +import test_function_pointer testers = [ # , demangled_tester # failing right now @@ -138,7 +139,8 @@ test_map_gcc5, test_argument_without_name, test_smart_pointer, - test_pattern_parser + test_pattern_parser, + test_function_pointer ] if 'posix' in os.name: diff --git a/unittests/test_function_pointer.py b/unittests/test_function_pointer.py new file mode 100644 index 00000000..15c1cb12 --- /dev/null +++ b/unittests/test_function_pointer.py @@ -0,0 +1,76 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Copyright 2004-2009 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +import unittest +import parser_test_case + +from pygccxml import parser +from pygccxml import declarations + + +class Test(parser_test_case.parser_test_case_t): + + def __init__(self, *args): + parser_test_case.parser_test_case_t.__init__(self, *args) + self.header = "test_function_pointer.hpp" + + def test_function_pointer(self): + """ + Test working with pointers and function pointers. + + """ + + decls = parser.parse([self.header], self.config) + global_ns = declarations.get_global_namespace(decls) + + # Test on a function pointer + criteria = declarations.variable_matcher(name="func1") + variables = declarations.matcher.find(criteria, global_ns) + + self.assertTrue(variables[0].name == "func1") + self.assertTrue( + isinstance(variables[0].decl_type, declarations.pointer_t)) + self.assertTrue( + str(variables[0].decl_type) == "void (*)( int,double ) *") + self.assertTrue( + declarations.is_calldef_pointer(variables[0].decl_type)) + self.assertTrue( + isinstance(declarations.remove_pointer(variables[0].decl_type), + declarations.free_function_type_t)) + + # Get the function (free_function_type_t) and test the return and + # argument types + function = variables[0].decl_type.base + self.assertTrue(isinstance(function.return_type, declarations.void_t)) + self.assertTrue( + isinstance(function.arguments_types[0], declarations.int_t)) + self.assertTrue( + isinstance(function.arguments_types[1], declarations.double_t)) + + # Test on a normal pointer + criteria = declarations.variable_matcher(name="myPointer") + variables = declarations.matcher.find(criteria, global_ns) + + self.assertTrue(variables[0].name == "myPointer") + self.assertTrue( + isinstance(variables[0].decl_type, declarations.pointer_t)) + self.assertFalse( + declarations.is_calldef_pointer(variables[0].decl_type)) + self.assertTrue( + isinstance(declarations.remove_pointer(variables[0].decl_type), + declarations.volatile_t)) + + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(Test)) + return suite + + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run(create_suite()) + +if __name__ == "__main__": + run_suite() From d4498a70db8e893f0708199322a1bcdaf2c93e15 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 28 Aug 2016 22:28:46 +0200 Subject: [PATCH 253/268] Add example demonstrating the inspection of function pointers --- docs/examples.rst | 8 +++ docs/examples/function-pointer/example.hpp | 6 +++ docs/examples/function-pointer/example.py | 59 ++++++++++++++++++++++ docs/examples/function-pointer/example.rst | 17 +++++++ 4 files changed, 90 insertions(+) create mode 100644 docs/examples/function-pointer/example.hpp create mode 100644 docs/examples/function-pointer/example.py create mode 100644 docs/examples/function-pointer/example.rst diff --git a/docs/examples.rst b/docs/examples.rst index 2303fa07..3aec197e 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -16,5 +16,13 @@ First examples examples/equality/example.rst examples/functions/example.rst examples/nested-types/example.rst + +Advanced examples +----------------- + +.. toctree:: + :maxdepth: 1 + + examples/function-pointer/example.rst examples/caching/example.rst examples/print-example/example.rst diff --git a/docs/examples/function-pointer/example.hpp b/docs/examples/function-pointer/example.hpp new file mode 100644 index 00000000..9c1cb460 --- /dev/null +++ b/docs/examples/function-pointer/example.hpp @@ -0,0 +1,6 @@ +// Copyright 2014-2016 Insight Software Consortium. +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// A function pointer +void (*myFuncPointer)(int, double); diff --git a/docs/examples/function-pointer/example.py b/docs/examples/function-pointer/example.py new file mode 100644 index 00000000..5a907453 --- /dev/null +++ b/docs/examples/function-pointer/example.py @@ -0,0 +1,59 @@ +# Copyright 2014-2016 Insight Software Consortium. +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +from pygccxml import utils +from pygccxml import declarations +from pygccxml import parser + +import os +import sys +import warnings +warnings.simplefilter("error", Warning) +# Find out the file location within the sources tree +this_module_dir_path = os.path.abspath( + os.path.dirname(sys.modules[__name__].__file__)) + +# Find out the c++ parser +generator_path, generator_name = utils.find_xml_generator() + +# Configure the xml generator +xml_generator_config = parser.xml_generator_configuration_t( + xml_generator_path=generator_path, + xml_generator=generator_name) + +# The c++ file we want to parse +filename = "example.hpp" +filename = this_module_dir_path + "/" + filename + +decls = parser.parse([filename], xml_generator_config) +global_namespace = declarations.get_global_namespace(decls) + +function = global_namespace.variables()[0] + +# Print the name of the function pointer +print(function.name) +# > myFuncPointer + +# Print the type of the declaration (it's just a pointer) +print(type(function.decl_type)) +# > + +# Check if this is a function pointer +print(declarations.is_calldef_pointer(function.decl_type)) +# > True + +# Remove the pointer part, to access the function's type +f_type = declarations.remove_pointer(function.decl_type) + +# Print the type +print(type(f_type)) +# > + +# Print the return type and the arguments of the function +print(f_type.return_type) +# > void + +# Print the return type and the arguments +print(str(f_type.arguments_types[0]), str(f_type.arguments_types[1])) +# > int, double diff --git a/docs/examples/function-pointer/example.rst b/docs/examples/function-pointer/example.rst new file mode 100644 index 00000000..8245a7f4 --- /dev/null +++ b/docs/examples/function-pointer/example.rst @@ -0,0 +1,17 @@ +================= +Function pointers +================= + +This example shows how to work with function pointers. + +Let's consider the following c++ file: + +.. literalinclude:: example.hpp + :language: c++ + :lines: 4- + +The following code allows you to extract information about the function pointer: + +.. literalinclude:: example.py + :language: python + :lines: 5,6,7,16-26,28- From 0d9a0f68db1d3443ed9c2d3e997c6559538f8360 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 29 Aug 2016 21:04:51 +0200 Subject: [PATCH 254/268] Document the get_global_namespace function --- pygccxml/declarations/namespace.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pygccxml/declarations/namespace.py b/pygccxml/declarations/namespace.py index 7894f847..de810685 100644 --- a/pygccxml/declarations/namespace.py +++ b/pygccxml/declarations/namespace.py @@ -283,6 +283,16 @@ def i_depend_on_them(self, recursive=True): def get_global_namespace(decls): + """ + Get the global namespace (::) from a declaration tree. + + Args: + decls (list[declaration_t]): a list of declarations + + Returns: + namespace_t: the global namespace_t object (::) + + """ found = [ decl for decl in scopedef.make_flatten(decls) if decl.name == '::' and isinstance(decl, namespace_t)] From d172cb59356156b525317c71372e891f01accad9 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 29 Aug 2016 22:06:25 +0200 Subject: [PATCH 255/268] Improve test error output --- unittests/type_traits_tester.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unittests/type_traits_tester.py b/unittests/type_traits_tester.py index 79e0cc31..f3ce1703 100644 --- a/unittests/type_traits_tester.py +++ b/unittests/type_traits_tester.py @@ -101,8 +101,8 @@ def __test_type_transformation(self, ns_name, transformer): declarations.is_same( transformed, tafter), - ("there is a difference between expected type({0}) " + - "and result({1}). typedef name: {2}").format( + ("there is a difference between expected type '{0}' " + + "and result '{1}'. typedef name: {2}").format( declarations.remove_declarated(tafter).decl_string, declarations.remove_declarated(transformed).decl_string, tbefore.decl_string)) From 8847a59c5862b6c95ccd57f8736d1312e1ef7cdd Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 29 Aug 2016 22:22:32 +0200 Subject: [PATCH 256/268] Extend function pointer test --- unittests/data/test_function_pointer.hpp | 8 +++++++- unittests/test_function_pointer.py | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/unittests/data/test_function_pointer.hpp b/unittests/data/test_function_pointer.hpp index bc248cab..d62abc7d 100644 --- a/unittests/data/test_function_pointer.hpp +++ b/unittests/data/test_function_pointer.hpp @@ -9,4 +9,10 @@ void (*func1)(int, double); // Another pointer, but not a function pointer -int const volatile* myPointer; \ No newline at end of file +int const volatile* myPointer; + +// A struct +struct some_struct_t{}; + +// Another function pointer +typedef void (some_struct_t::*x8)(); diff --git a/unittests/test_function_pointer.py b/unittests/test_function_pointer.py index 15c1cb12..efd02d1e 100644 --- a/unittests/test_function_pointer.py +++ b/unittests/test_function_pointer.py @@ -62,6 +62,20 @@ def test_function_pointer(self): isinstance(declarations.remove_pointer(variables[0].decl_type), declarations.volatile_t)) + # Test on function pointer in struct (x8) + for d in global_ns.declarations: + if d.name == "x8": + self.assertTrue( + isinstance(d.decl_type, declarations.pointer_t)) + self.assertTrue(declarations.is_calldef_pointer(d.decl_type)) + self.assertTrue( + isinstance( + declarations.remove_pointer(d.decl_type), + declarations.member_function_type_t)) + self.assertTrue( + str(declarations.remove_pointer(d.decl_type)) == + "void ( ::some_struct_t::* )( )") + def create_suite(): suite = unittest.TestSuite() From b6a179a1022b504cc3588593c7a2e043b2b83860 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Mon, 29 Aug 2016 22:24:20 +0200 Subject: [PATCH 257/268] Fix failing remove_pointers tests The x7 case was easy to fix. The x8 case could not be fixed and was just disabled with a comment. It can be re-enabled if we find a way to write the correct c++ code here. Anyway; that case is covered by the test_function_pointer test. --- unittests/data/type_traits.hpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/unittests/data/type_traits.hpp b/unittests/data/type_traits.hpp index b46d8642..8408bf31 100644 --- a/unittests/data/type_traits.hpp +++ b/unittests/data/type_traits.hpp @@ -345,7 +345,13 @@ namespace before{ typedef int* const x5; typedef int* volatile x6; typedef void(*x7)(); - typedef void (some_struct_t::*x8)(); + // typedef void (some_struct_t::*x8)(); + // The last test is disabled but is covered by test_function_pointer.py + // I do not know how to write the c++ code in the after pointer removal + // namespace, as just removing the * will not work. But as this case is + // covered elsewhere, it is okay to skip that one. + // TODO: decide if last test (some_struct::*x8) needs to be removed + // completely or written differently. } namespace after{ @@ -355,8 +361,8 @@ namespace after{ typedef some_struct_t x4; typedef int const x5; typedef int volatile x6; - typedef void(*x7)(); - typedef void (some_struct_t::*x8)(); + typedef void(x7)(); + // typedef void (some_struct_t::*x8)(); } } From 53f5068348a50ec4a0a79b5e81a28441f5e0d8b3 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 31 Aug 2016 20:42:48 +0200 Subject: [PATCH 258/268] Remove quantifiedcode badge QuantifiedCode will be shutting down on October 1st 2016. --- README.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.rst b/README.rst index 5a00eb98..9edf7cc9 100644 --- a/README.rst +++ b/README.rst @@ -10,9 +10,6 @@ pygccxml .. image:: https://readthedocs.org/projects/pygccxml/badge/?version=develop :target: http://pygccxml.readthedocs.io/en/develop/?badge=develop :alt: Documentation status -.. image:: https://www.quantifiedcode.com/api/v1/project/117af14ef32a455fb7b3762e21083fb3/snapshot/origin:develop:HEAD/badge.svg - :target: https://www.quantifiedcode.com/app/project/117af14ef32a455fb7b3762e21083fb3?branch=origin%2Fdevelop&tab=basics - :alt: Code quality status pygccxml is a specialized XML reader that reads the output from CastXML or GCCXML. It provides a simple framework to navigate C++ declarations, using Python classes. From 1e42f6cbb249fec9857842570d57ab57af26c50e Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 31 Aug 2016 23:48:21 +0200 Subject: [PATCH 259/268] Add a FAQ with a section about performance (#56) --- docs/faq.rst | 47 +++++++++++++++++++++++++++++++++++++++++++++++ docs/index.rst | 1 + 2 files changed, 48 insertions(+) create mode 100644 docs/faq.rst diff --git a/docs/faq.rst b/docs/faq.rst new file mode 100644 index 00000000..d7b6dfe3 --- /dev/null +++ b/docs/faq.rst @@ -0,0 +1,47 @@ +FAQ +=== + + +Performance +----------- + +pygccxml is being regularly optimised for performance, but it still may be slow +in certain cases. + +Before all, it is highly recommended to benchmark your application if performance +is important to you. There are multiple tools out there for benchmarking python +applications. We currently are using the following two command lines / tools: + + | python -m cProfile -o profile_data.pyprof script_to_profile.py + | pyprof2calltree -i profile_data.pyprof -k + +Of course optimising pygccxml alone will not help in all cases. The bottlenecks can also be +in the code calling pygccxml, to make sure to benchmark the whole process. +Any help on the performance side is also welcome. + +Some things you may try (in order of priority): + +1) You might want to consider making the declaration tree as small as possible + and only store those declarations that somehow have an influence on the bindings. + Ideally, this is done as early as possible and luckily castxml and gccxml + provide an option that allows you to reduce the number of declarations that + need to be parsed. + + You can specify one or more declarations using the ``-fxml-start`` (gccxml) or + ``-castxml-start`` (castxml) options when running the xml generator. For + example, if you specify the name of a particular class, only this class + and all its members will get written. Ideally, your project should already use + a dedicated namespace, which you can then use as a starting point. + All declarations stemming from system headers will be ignored (except + for those declarations that are actually used within your library). + + In the pygccxml package you can set the value for these flags by using + the ``start_with_declarations`` attribute of the ``pygccxml.parser.config_t`` + object that you are passing to the parser. + +2) You can pass the following flag to the *read_files* method: + + compilation_mode=pygccxml.parser.COMPILATION_MODE.ALL_AT_ONCE + +3) If you want to cache the declarations tree, there is a caching mechanism provided + by pygccxml. You will find an example of this mechanism in the examples section. diff --git a/docs/index.rst b/docs/index.rst index 871a31a2..5e826338 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -52,6 +52,7 @@ Documentation contents install examples documentation + faq query_interface design users From ed8dd37e3931581e6808c8d524b7636bb8296433 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Wed, 31 Aug 2016 23:50:40 +0200 Subject: [PATCH 260/268] Link to FAQ in readme --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index 9edf7cc9..3c65619c 100644 --- a/README.rst +++ b/README.rst @@ -23,6 +23,8 @@ Documentation and examples The documentation can be found `here `_, examples can be found `here `_. +A `FAQ `_. is also available and may answer some of your questions. + Contact us ---------- From 082474498d8f540189b07728fc3e270c417ae08e Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 1 Sep 2016 21:43:13 +0200 Subject: [PATCH 261/268] Fix typo (remove dot) --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 3c65619c..a46edda9 100644 --- a/README.rst +++ b/README.rst @@ -23,7 +23,7 @@ Documentation and examples The documentation can be found `here `_, examples can be found `here `_. -A `FAQ `_. is also available and may answer some of your questions. +A `FAQ `_ is also available and may answer some of your questions. Contact us ---------- From d2b8e43d7c6fd4affdfee036c9fb3a2e67f3d1c9 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 1 Sep 2016 22:29:35 +0200 Subject: [PATCH 262/268] Document __va_list_tag declarations in FAQ --- docs/faq.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/faq.rst b/docs/faq.rst index d7b6dfe3..a6918600 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -45,3 +45,20 @@ Some things you may try (in order of priority): 3) If you want to cache the declarations tree, there is a caching mechanism provided by pygccxml. You will find an example of this mechanism in the examples section. + + +\_\_va_list_tag and other hidden declarations +--------------------------------------------- + +When parsing with CastXML, the XML tree can contain declarations named +``__va_list_tag``. If the compiler is llvm 3.9, ``__NSConstantString_tag`` +and ``__NSConstantString`` declarations may also be present. + +These declarations are internal declarations, coming from the std c++ library +headers you include, and are often not needed. They are for example polluting +the declarations tree when running pyplusplus. + +By default, pygccxml will ignore these declarations. +To still read these declarations from the xml file, a config flag can +be set (``config.flags = ["f1"]``), or a flag can be passed as argument the +config setup (``flags=["f1"]``). From 3452d2b77c60fe25dcc4b86dd0fde871393e47b3 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 1 Sep 2016 23:15:28 +0200 Subject: [PATCH 263/268] Add pylint config and script to run pylint --- unittests/pylint.cfg | 361 +++++++++++++++++++++++++++++++++++++++++++ unittests/run_pylint | 8 + 2 files changed, 369 insertions(+) create mode 100644 unittests/pylint.cfg create mode 100755 unittests/run_pylint diff --git a/unittests/pylint.cfg b/unittests/pylint.cfg new file mode 100644 index 00000000..0fdbc59e --- /dev/null +++ b/unittests/pylint.cfg @@ -0,0 +1,361 @@ +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Pickle collected data for later comparisons. +persistent=yes + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Use multiple processes to speed up Pylint. +jobs=1 + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=C0103,C0111,E1608,W1627,E1601,E1603,E1602,E1605,E1604,E1607,E1606,W1621,W1620,W1623,W1622,W1625,W1624,W1609,W1608,W1607,W1606,W1605,W1604,W1603,W1602,W1601,W1639,I0021,W1638,I0020,W1618,W1619,W1630,W1626,W1637,W1634,W1635,W1610,W1611,W1612,W1613,W1614,W1615,W1616,W1617,W1632,W1633,W0704,W1628,W1629,W1636 + +# Things that ware disabled specifically for pygccxml +# Some of these may be enable later +# C0103: Invalid class name +# C0111: Missing method docstring (missing-docstring) + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +reports=yes + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +msg-template={msg_id}:{line:3d},{column:2d}: {msg} ({symbol}) + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_$|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + + +[BASIC] + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,input + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Regular expression matching correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for function names +function-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for variable names +variable-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Naming hint for constant names +const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression matching correct attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for attribute names +attr-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for argument names +argument-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming hint for class attribute names +class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming hint for inline iteration names +inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Naming hint for class names +class-name-hint=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Naming hint for module names +module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression matching correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for method names +method-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=__.*__ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis +ignored-modules= + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). +ignored-classes=SQLObject, optparse.Values, thread._local, _thread._local + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members=REQUEST,acl_users,aq_parent + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=100 + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + +# List of optional constructs for which whitespace checking is disabled +no-space-check=trailing-comma,dict-separator + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception \ No newline at end of file diff --git a/unittests/run_pylint b/unittests/run_pylint new file mode 100755 index 00000000..95602e3c --- /dev/null +++ b/unittests/run_pylint @@ -0,0 +1,8 @@ +#!/bin/bash + +# Get current directory +DIRECTORY=$( cd "$( dirname "$0" )" && pwd ) +# Get parent directory +DIR=${DIRECTORY%/*} + +pylint --rcfile=$DIRECTORY"/pylint.cfg" $DIR/pygccxml/declarations From 24c259c2008def4a1c582509c169c50fccec2429 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 1 Sep 2016 23:35:40 +0200 Subject: [PATCH 264/268] Do not shadow name from outer scope --- pygccxml/declarations/scopedef.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pygccxml/declarations/scopedef.py b/pygccxml/declarations/scopedef.py index e7d0a5a7..5316081e 100644 --- a/pygccxml/declarations/scopedef.py +++ b/pygccxml/declarations/scopedef.py @@ -456,9 +456,9 @@ def __findout_range(self, name, decl_type, recursive): name = None if name and decl_type: - matcher = scopedef_t._impl_matchers[scopedef_t.decl](name=name) - if matcher.is_full_name(): - name = matcher.decl_name_only + impl_match = scopedef_t._impl_matchers[scopedef_t.decl](name=name) + if impl_match.is_full_name(): + name = impl_match.decl_name_only if recursive: self._logger.debug( 'query has been optimized on type and name') From 910267a2b3ba6660a742d74b5f346bdb566708b6 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Thu, 1 Sep 2016 23:51:15 +0200 Subject: [PATCH 265/268] Simplify by using get with default on dicts --- pygccxml/declarations/scopedef.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/pygccxml/declarations/scopedef.py b/pygccxml/declarations/scopedef.py index 5316081e..82217bb8 100644 --- a/pygccxml/declarations/scopedef.py +++ b/pygccxml/declarations/scopedef.py @@ -462,17 +462,11 @@ def __findout_range(self, name, decl_type, recursive): if recursive: self._logger.debug( 'query has been optimized on type and name') - if name in self._type2name2decls[decl_type]: - return self._type2name2decls[decl_type][name] - else: - return [] + return self._type2name2decls[decl_type].get(name, []) else: self._logger.debug( 'non recursive query has been optimized on type and name') - if name in self._type2name2decls_nr[decl_type]: - return self._type2name2decls_nr[decl_type][name] - else: - return [] + return self._type2name2decls_nr[decl_type].get(name, []) elif decl_type: if recursive: self._logger.debug('query has been optimized on type') From 06700e563e4a135c97ad476699c1200bb0f02699 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 4 Sep 2016 11:50:08 +0200 Subject: [PATCH 266/268] Update changelog for version 1.8.0 --- CHANGELOG.md | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22266531..05785333 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,41 +1,40 @@ Changes ======= -Version 1.8.0 (not yet released) --------------------------------- +Version 1.8.0 +------------- -* find_xml_generator will now look for castxml first +1. ```find_xml_generator``` will now look for castxml first -* Do not allow to use the GCCXML provided by newer gccxml debian packages. +2. Do not allow to use the GCCXML provided by newer gccxml debian packages. It is a wrapper around CastXML which can confuse pygccxml. You should use the castxml package and the CastXML binary instead. If you really want to use gccxml, the gccxml.real binary from the gccxml debian package can still be used. -* Fix parsing of boost/locale.hpp code. +3. Fix parsing of ```boost/locale.hpp``` code. Templated class instantiations with specializations are now better supported, specifically when containing parentheses: - myClass(const std::string &, const std::string &)> obj; + ```myClass(const std::string &, const std::string &)> obj;``` -* When using the ```remove_pointer``` function on a function pointer, the +4. When using the ```remove_pointer``` function on a function pointer, the ```remove_pointer``` function now correctly returns a ```calldef_type_t```. -* ```declarations.is_string```, ```declarations.is_std_wstring```, +5. ```declarations.is_string```, ```declarations.is_std_wstring```, ```declarations.is_std_ostream``` and ```declarations.is_std_wostream``` now correctly work when a the type is also a reference. Example: ```declarations.is_string``` returned false for ```typedef std::string& x3;```; it will return true now. -* General code style overhaul (with the help of quantifiedcode.com) - -* Added a bunch of new examples +6. General code style overhaul (with the help of quantifiedcode.com) -* Documentation update and cleanup +7. Added a bunch of new examples and documentation update and cleanup -* [Removals] Remove compiler attribute in declarations.py and gccxml_path from config.py +8. [Removals] Remove ```compiler``` attribute in declarations.py and + ```gccxml_path``` from config.py These were deprecated in pygccxml v1.7.0, and definitively removed for v1.8.0 -* [Deprecations] +9. [Deprecations] * The ```binary_parsers``` module was deprecated. It seems that this module is not used by other third-party projects, at least a quick search on GitHub did not give any interesting usage. Also, this code is not tested, and @@ -57,18 +56,18 @@ Version 1.8.0 (not yet released) - decl.find_noncopyable_vars() method => declarations.find_noncopyable_vars(decl) - decl.find_copy_constructor() method => declarations.find_copy_constructor(decl) - decl.has_vtable argument => declarations.has_vtable(decl) - * ```constructor_t``` + * In ```constructor_t``` - ctor.is_copy_constructor attribute => declarations.is_copy_constructor(ctor) - ctor.is_trivial_constructor attribute => declarations.is_trivial_constructor(ctor) - * Deprecate the ns() method. The namespace() method can be used instead. + * Deprecate the ```ns()``` method. The ```namespace()``` method can be used instead. - * Deprecate etree_scanner_t and etree_saxifier_t classes. - The most efficient xml scanner class is the ietree_scanner_t class, which + * Deprecate ```etree_scanner_t``` and ```etree_saxifier_t``` classes. + The most efficient xml scanner class is the ```ietree_scanner_t``` class, which is the one used since many years now. - * The [gccxml] section used in the configuration file is now deprecated. - Please use [xml_generator] instead. + * The ```[gccxml]``` section used in the configuration file is now deprecated. + Please use ```[xml_generator]``` instead. Version 1.7.6 From 8a860cf2e0449e36620595cb200266cfdb46798e Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 4 Sep 2016 11:52:00 +0200 Subject: [PATCH 267/268] Bump version number to 1.8.0 --- docs/conf.py | 4 ++-- pygccxml/__init__.py | 2 +- setup.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 56e7731c..afeaacf7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -55,9 +55,9 @@ # built documents. # # The short X.Y version. -version = '1.7.6' +version = '1.8.0' # The full version, including alpha/beta/rc tags. -release = '1.7.6' +release = '1.8.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/pygccxml/__init__.py b/pygccxml/__init__.py index a29ac901..4ce44f7c 100644 --- a/pygccxml/__init__.py +++ b/pygccxml/__init__.py @@ -40,4 +40,4 @@ # TODO: # 1. Add "explicit" property for constructors -__version__ = '1.7.6' +__version__ = '1.8.0' diff --git a/setup.py b/setup.py index b2f55b54..67cb8387 100644 --- a/setup.py +++ b/setup.py @@ -7,14 +7,14 @@ from setuptools import setup setup(name="pygccxml", - version="1.7.6", + version="1.8.0", author="Roman Yakovenko", author_email="roman yakovenko at gmail com", maintainer="Michka Popoff and the Insight Software Consortium", maintainer_email="castxml@public.kitware.com", description="Python package for easy C++ declarations navigation.", url="https://github.com/gccxml/pygccxml", - download_url="https://github.com/gccxml/pygccxml/archive/v1.7.6.tar.gz", + download_url="https://github.com/gccxml/pygccxml/archive/v1.8.0.tar.gz", license="Boost", keywords="C++, declaration parser, CastXML, gccxml", packages=["pygccxml", From 40bb41191e847b5bd9baf2bb249ed3d650bfda02 Mon Sep 17 00:00:00 2001 From: Michka Popoff Date: Sun, 4 Sep 2016 11:52:45 +0200 Subject: [PATCH 268/268] Update filename in doc --- docs/releasing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/releasing.rst b/docs/releasing.rst index a0611eba..d13a5fbb 100644 --- a/docs/releasing.rst +++ b/docs/releasing.rst @@ -11,7 +11,7 @@ Modify the version numbers in: ``docs/conf.py`` -Do not forget to document the changes in the ``docs/history.rst`` file. +Do not forget to document the changes in the ``CHANGELOG.md`` file. Uploading to pypi -----------------