File Coverage

blib/lib/Autodia/Handler/python.pm
Criterion Covered Total %
statement 15 126 11.9
branch 0 58 0.0
condition 0 2 0.0
subroutine 5 7 71.4
pod n/a
total 20 193 10.3


line stmt bran cond sub pod time code
1             ################################################################
2             # AutoDIA - Automatic Dia XML. (C)Copyright 2001 A Trevena #
3             # #
4             # AutoDIA comes with ABSOLUTELY NO WARRANTY; see COPYING file #
5             # This is free software, and you are welcome to redistribute #
6             # it under certain conditions; see COPYING file for details #
7             ################################################################
8             package Autodia::Handler::python;
9              
10             require Exporter;
11              
12 1     1   1753 use strict;
  1         2  
  1         37  
13              
14 1     1   5 use vars qw($VERSION @ISA @EXPORT);
  1         3  
  1         55  
15 1     1   5 use Autodia::Handler;
  1         3  
  1         45  
16              
17             @ISA = qw(Autodia::Handler Exporter);
18              
19 1     1   6 use Autodia::Diagram;
  1         2  
  1         21  
20 1     1   4 use Data::Dumper;
  1         3  
  1         1763  
21              
22             #---------------------------------------------------------------
23              
24             #####################
25             # Constructor Methods
26              
27             # new inherited from Autodia::Handler
28              
29             #------------------------------------------------------------------------
30             # Access Methods
31              
32             # parse_file inherited from Autodia::Handler
33              
34             #-----------------------------------------------------------------------------
35             # Internal Methods
36              
37             # _initialise inherited from Autodia::Handler
38              
39             sub _parse { # parses python source code
40 0     0     my $self = shift;
41 0           my $fh = shift;
42 0           my $filename = shift;
43              
44 0           warn "_parse_file called with $self, $fh, $filename\n";
45              
46 0           my %config = %{$self->{Config}};
  0            
47 0           my $Diagram = $self->{Diagram};
48              
49             # set up local variables for parsing
50 0           $self->{in_comment} = 0;
51 0           my $module_name = $filename;
52 0           $module_name =~ s/^.*?\/?(\w+)\.py$/$1/;
53 0           my $in_class = 0;
54 0           my $current_class = $module_name;
55 0           my $exit_depth = -1;
56              
57 0           my $Module = Autodia::Diagram::Class->new($module_name);
58 0           my $exists = $Diagram->add_class($Module);
59 0 0         my $Class = $Module = $exists if ($exists);
60              
61 0           my %aliases = ();
62              
63             # process file
64 0           my $class_count = 0;
65 0           foreach my $line (<$fh>) {
66 0 0         next if $self->_discard_line (\$line);
67             # count spaces / tabs to see how deep indented
68 0           my $depth = 0;
69 0           foreach (split(//,$line)) {
70 0 0         last if (/\S/);
71 0           $depth++;
72             }
73 0 0         if ($depth == $exit_depth) {
74 0           $in_class = 0;
75 0           $current_class = $module_name;
76 0           $Class = $Module;
77             }
78              
79             # catch methods and subs
80 0 0         if ( $line =~ m/^[\s\t]*def\s+(\S+)\s*\((.*)\):/ ) {
81 0           my %method = ( "name" => $1, );
82 0 0         $method{"visibility"} = ($method{"name"} =~ m/^\_/) ? 1 : 0;
83 0   0       my $params = $2 || '';
84 0 0         if ($params) {
85 0           foreach (split(/\s*,\s*/,$params)) {
86 0           push (@{$method{"Params"}},{Name => $_, Val => '',});
  0            
87             }
88             }
89 0           $Class->add_operation(\%method);
90             }
91              
92             # catch class
93 0 0         if ( $line =~ /^class\s+(\w+).*:/ ) {
94 0           my $classname = $1;
95 0           $current_class = "$module_name.$classname";
96 0 0         last if ($self->skip($classname));
97 0           $Class = Autodia::Diagram::Class->new("$module_name.$classname");
98 0           my $exists = $Diagram->add_class($Class);
99 0 0         $Class = $exists if ($exists);
100 0           $aliases{$classname} = $Class;
101              
102 0           warn "got class name : $classname\n";
103 0           warn " line : $line \n";
104 0 0         if ( $line =~ /\((.*)\)/) {
105 0           my @superclasses = split(/[\,\s]/,$1);
106 0           foreach my $super (@superclasses) {
107             # create superclass
108 0           warn "have superclass : $super\n";
109 0 0         next unless ($super=~/\S/);
110 0           my $Superclass;
111             # check if superclass exists already
112 0 0         if ($aliases{$super}) {
113 0           $Superclass = $aliases{$super};
114 0           warn "found alias for superclass $super - ",$Superclass->Name , "\n";
115             } else {
116 0           $Superclass = Autodia::Diagram::Superclass->new($super);
117             # add superclass to diagram
118 0           my $exists_already = $Diagram->add_superclass($Superclass);
119 0 0         if (ref $exists_already) {
120 0           warn "superclass exists already";
121 0           $Superclass = $exists_already;
122             }
123 0           $aliases{$super} = $Superclass;
124             }
125             # create new inheritance
126 0           my $Inheritance = Autodia::Diagram::Inheritance->new($Class, $Superclass);
127             # add inheritance to superclass
128 0           $Superclass->add_inheritance($Inheritance);
129             # add inheritance to class
130 0           $Class->add_inheritance($Inheritance);
131             # add inheritance to diagram
132 0           $Diagram->add_inheritance($Inheritance);
133             }
134             }
135 0           $in_class = 1;
136 0           $exit_depth = $depth;
137             }
138              
139             # catch object attributes via self.foo or this.foo
140 0 0         if ( $line =~ /(self|this)\.(\w+)\.?/ ) {
141 0           my $attribute = $2;
142 0 0         my $attribute_visibility = ( $attribute =~ m/^\_/ ) ? 1 : 0;
143 0           $Class->add_attribute({
144             name => $attribute,
145             visibility => $attribute_visibility,
146             value => '',
147             });
148             }
149 0 0         if ( $line =~ /import/ ) {
150 0           my $dependancy;
151 0 0         if ($line =~ /from\s+(\w+)\s+import/) {
    0          
152 0           $dependancy = $1;
153             } elsif ($line =~ /\s*import\s+(\w+)/) {
154 0           $dependancy = $1;
155             } else {
156             # not supported
157             }
158 0 0         if ($dependancy) {
159             # create component
160 0           my $Component = Autodia::Diagram::Component->new($dependancy);
161             # add component to diagram
162 0           my $exists = $Diagram->add_component($Component);
163             # replace component if redundant
164 0 0         if (ref $exists) {
165 0           $Component = $exists;
166             }
167             # create new dependancy
168 0           my $Dependancy = Autodia::Diagram::Dependancy->new($Class, $Component);
169             # add dependancy to diagram
170 0           $Diagram->add_dependancy($Dependancy);
171             # add dependancy to class
172 0           $Class->add_dependancy($Dependancy);
173             # add dependancy to component
174 0           $Component->add_dependancy($Dependancy);
175             }
176             }
177             }
178             }
179             ##########################################
180              
181              
182             sub _discard_line
183             {
184 0     0     my $self = shift;
185 0           my $line = shift;
186 0           my $discard = 0;
187              
188             SWITCH:
189             {
190 0 0         if ($$line =~ /"""/) # if line is a comment discard
  0            
191             {
192 0           $$line =~ s/""".*"""//;
193 0 0         if ($self->{in_comment}) {
194 0 0         if ($$line =~ /"""(\s*\w[\w\s]*)/) {
195 0           $self->{in_comment} = 0;
196 0           $$line = $1;
197             } else {
198 0           $self->{in_comment} = 0;
199 0           $discard = 1;
200             }
201             } else {
202 0 0         if ($$line =~ /^(\s*[\w\s]*)"""/) {
203 0           $self->{in_comment} = 1;
204 0           $$line = $1;
205             } else {
206 0           $discard = 1;
207             }
208             }
209 0           last SWITCH;
210             } else {
211 0 0         $discard = 1 if ($self->{in_comment});
212             }
213              
214 0 0         if ($$line =~ /#/) {
215 0 0         if ($$line =~ /^(\s*\w[\w\s]*)#/) {
216 0           $$line = $1;
217             } else {
218 0           $discard = 1;
219             }
220 0           last SWITCH;
221             }
222             } # end SWITCH
223              
224 0 0         $discard = 1 if ($$line =~ m/^\s*$/); # if line is blank or white space discard
225 0           return $discard;
226             }