line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Data::Faker; |
2
|
7
|
|
|
7
|
|
218935
|
use vars qw($VERSION); $VERSION = '0.10'; |
|
7
|
|
|
|
|
16
|
|
|
7
|
|
|
|
|
1234
|
|
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
=head1 NAME |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
Data::Faker - Perl extension for generating fake data |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 SYNOPSIS |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use Data::Faker; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
my $faker = Data::Faker->new(); |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
print "Name: ".$faker->name."\n"; |
15
|
|
|
|
|
|
|
print "Company: ".$faker->company."\n"; |
16
|
|
|
|
|
|
|
print "Address: ".$faker->street_address."\n"; |
17
|
|
|
|
|
|
|
print " ".$faker->city.", ".$faker->us_state_abbr." ".$faker->us_zip_code."\n"; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head1 DESCRIPTION |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
This module creates fake (but reasonable) data that can be used for things |
22
|
|
|
|
|
|
|
such as filling databases with fake information during development of |
23
|
|
|
|
|
|
|
database related applications. |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=cut |
26
|
|
|
|
|
|
|
|
27
|
7
|
|
|
7
|
|
40
|
use strict; |
|
7
|
|
|
|
|
13
|
|
|
7
|
|
|
|
|
318
|
|
28
|
7
|
|
|
7
|
|
37
|
use warnings; |
|
7
|
|
|
|
|
15
|
|
|
7
|
|
|
|
|
329
|
|
29
|
7
|
|
|
7
|
|
40
|
use File::Spec (); |
|
7
|
|
|
|
|
12
|
|
|
7
|
|
|
|
|
180
|
|
30
|
7
|
|
|
7
|
|
33
|
use Carp 'croak'; |
|
7
|
|
|
|
|
15
|
|
|
7
|
|
|
|
|
3550
|
|
31
|
|
|
|
|
|
|
my %plugins; |
32
|
|
|
|
|
|
|
my @always_import; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head1 OBJECT METHODS |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=over 4 |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=item new() |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
Object constructor. As a shortcut, you can pass names of plugin modules to |
41
|
|
|
|
|
|
|
load to new(), although this does not actually restrict the functions available |
42
|
|
|
|
|
|
|
to the object, it just causes those plugins to be loaded if they haven't been |
43
|
|
|
|
|
|
|
loaded already. All Data::Faker objects in one interpreter share the plugin |
44
|
|
|
|
|
|
|
data, so that multiple objects don't multiply the memory requirements. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=cut |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub new { |
49
|
14
|
|
|
14
|
1
|
31301
|
my $pack = shift; |
50
|
14
|
|
|
|
|
36
|
my $self = {}; |
51
|
14
|
|
|
|
|
37
|
bless($self,$pack); |
52
|
14
|
|
|
|
|
49
|
my @import = (@_,@always_import); |
53
|
14
|
100
|
|
|
|
57
|
unless(@import) { push(@import,'*'); } |
|
2
|
|
|
|
|
6
|
|
54
|
14
|
|
|
|
|
37
|
foreach my $import (@import) { |
55
|
14
|
|
|
|
|
41
|
foreach(@INC) { |
56
|
154
|
|
|
|
|
9760
|
for(glob(File::Spec->catfile($_, qw/Data Faker/,"$import.pm"))) { |
57
|
168
|
100
|
66
|
|
|
43131
|
require $_ if -f $_ && -r _; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
} |
61
|
14
|
|
|
|
|
95
|
return $self; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
27
|
|
|
27
|
|
126
|
sub import { my $self = shift; push(@always_import,@_); } |
|
27
|
|
|
|
|
39018
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=item methods(); |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
Return a list of the methods that have been provided by all of the loaded |
69
|
|
|
|
|
|
|
plugins. |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=cut |
72
|
|
|
|
|
|
|
|
73
|
7
|
|
|
7
|
1
|
166
|
sub methods { return keys %Data::Faker::plugins; } |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=item register_plugin(); |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
Plugin modules call register_plugin() to provide data methods. See any of |
78
|
|
|
|
|
|
|
the included plugin modules for examples. |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=cut |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub register_plugin { |
83
|
238
|
|
|
238
|
1
|
396
|
my $self = shift; |
84
|
238
|
|
|
|
|
442
|
my @functions = @_; |
85
|
|
|
|
|
|
|
|
86
|
238
|
|
|
|
|
549
|
push(@{$Data::Faker::plugins{shift()}}, shift()) while @_; |
|
238
|
|
|
|
|
1332
|
|
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
7
|
|
|
7
|
|
61
|
use vars qw($AUTOLOAD); |
|
7
|
|
|
|
|
13
|
|
|
7
|
|
|
|
|
4761
|
|
90
|
|
|
|
|
|
|
sub AUTOLOAD { |
91
|
247
|
|
|
247
|
|
57817
|
my $self = shift; |
92
|
247
|
|
|
|
|
344
|
my $al = $AUTOLOAD; |
93
|
247
|
|
|
|
|
1311
|
$al =~ s/.*:://; |
94
|
247
|
50
|
|
|
|
459
|
my @data = @{$Data::Faker::plugins{$al} || []}; |
|
247
|
|
|
|
|
1237
|
|
95
|
247
|
50
|
|
|
|
540
|
croak "No data found for method '$al'" unless @data; |
96
|
|
|
|
|
|
|
|
97
|
247
|
|
|
|
|
932
|
my $data = $data[rand(@data)]; |
98
|
|
|
|
|
|
|
|
99
|
247
|
|
|
|
|
272
|
my $result; |
100
|
247
|
50
|
|
|
|
897
|
if(! ref($data)) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
101
|
0
|
|
|
|
|
0
|
$result = $data; |
102
|
|
|
|
|
|
|
} elsif(ref($data) eq 'ARRAY') { |
103
|
171
|
|
|
|
|
229
|
$result = $data->[rand(@{$data})]; |
|
171
|
|
|
|
|
601
|
|
104
|
|
|
|
|
|
|
} elsif(ref($data) eq 'CODE') { |
105
|
76
|
|
|
|
|
250
|
$result = $data->($self); |
106
|
|
|
|
|
|
|
} else { |
107
|
0
|
|
|
|
|
0
|
croak "Don't know what to do with result of type '".ref($data)."'"; |
108
|
|
|
|
|
|
|
} |
109
|
247
|
|
|
|
|
701
|
$result =~ s/\0//g; |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# replace any tokens that need expansion |
112
|
247
|
|
|
|
|
320
|
$result =~ s/\\\$/\0/g; |
113
|
247
|
|
|
|
|
698
|
while($result =~ /\$(\w+)/) { |
114
|
87
|
|
|
|
|
197
|
my $what = $1; |
115
|
87
|
|
|
|
|
566
|
my $r = $self->$what(); |
116
|
87
|
|
|
|
|
17380
|
$result =~ s/\$$what/$r/; |
117
|
|
|
|
|
|
|
} |
118
|
247
|
|
|
|
|
295
|
$result =~ s/\0/\$/g; |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# replace any number needing expansion |
121
|
247
|
|
|
|
|
907
|
$result =~ s/\\#/\0/g; |
122
|
247
|
|
|
|
|
379
|
$result =~ s/#/int(rand(10))/ge; |
|
59
|
|
|
|
|
127
|
|
123
|
247
|
|
|
|
|
291
|
$result =~ s/\0/#/g; |
124
|
|
|
|
|
|
|
|
125
|
247
|
|
|
|
|
2880
|
return $result; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
0
|
|
|
0
|
|
|
sub DESTROY {} |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=back |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=head1 LOADING PLUGINS |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
You can specify which plugins to load by including just the base part of their |
135
|
|
|
|
|
|
|
name as an argument when loading the module with 'use'. For example if you |
136
|
|
|
|
|
|
|
only wanted to use data from the Data::Faker::Name module, you would load |
137
|
|
|
|
|
|
|
Data::Faker like this: |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
use Data::Faker qw(Name); |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
By default any modules matching Data::Faker::* in any directory in @INC |
142
|
|
|
|
|
|
|
will be loaded. You can also pass plugin names when calling the new() method, |
143
|
|
|
|
|
|
|
and they will be loaded if not already in memory. See L. |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=head1 WRITING PLUGINS |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
Writing a plugin to provide new kinds of data is easy, all you have to do is |
148
|
|
|
|
|
|
|
create a module named Data::Faker::SomeModuleName that inherits from |
149
|
|
|
|
|
|
|
Data::Faker. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
To provide data, the plugin merely needs to call the register_plugin function |
152
|
|
|
|
|
|
|
with one or more pairs of function name and function data, like this: |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
#!/usr/bin/perl -w |
155
|
|
|
|
|
|
|
use strict; |
156
|
|
|
|
|
|
|
use warnings; |
157
|
|
|
|
|
|
|
use Data::Faker; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
my $faker = Data::Faker->new(); |
160
|
|
|
|
|
|
|
print "My fake data is ".$faker->some_data_function."\n"; |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
package Data::Faker::SomeData; |
163
|
|
|
|
|
|
|
use base 'Data::Faker'; |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
__PACKAGE__->register_plugin( |
166
|
|
|
|
|
|
|
some_data_function => [qw(foo bar baz gazonk)], |
167
|
|
|
|
|
|
|
another_data_item => sub { return '$some_data_function' }, |
168
|
|
|
|
|
|
|
); |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
The first argument is the method that will be made available to your object, |
171
|
|
|
|
|
|
|
the second is a data source. If the data source is not a reference, it will |
172
|
|
|
|
|
|
|
simply be returned as the data, if it is a reference to an array, a random |
173
|
|
|
|
|
|
|
element from the array will be returned, and if it is a subroutine reference, |
174
|
|
|
|
|
|
|
the subroutine will be run and the results will be returned. The data that |
175
|
|
|
|
|
|
|
your data source provides is checked for two things, tokens (that look like |
176
|
|
|
|
|
|
|
perl variables, starting with a $), and numeric indicators (#). Any tokens |
177
|
|
|
|
|
|
|
found will be replaced with their values, and any numeric indicators will be |
178
|
|
|
|
|
|
|
replaced with random numbers. You can include a literal $ or # by prefacing |
179
|
|
|
|
|
|
|
it with a backslash. If you load more than one module that defines the same |
180
|
|
|
|
|
|
|
function, it has an additive effect, when the function is called one of the |
181
|
|
|
|
|
|
|
data sources provided will be selected at random and then it will be called |
182
|
|
|
|
|
|
|
to get a piece of data. |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
Some data source examples: |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
__PACKAGE__->register_plugin( |
187
|
|
|
|
|
|
|
age => ['#','##'], |
188
|
|
|
|
|
|
|
monetary_amount => ['\$####.##','\$###.##', '\$##.##', '\$#.##'], |
189
|
|
|
|
|
|
|
adult_age => sub { int(rand(70)+18) }, |
190
|
|
|
|
|
|
|
); |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
If your data source is a code reference, it will receive the calling object |
193
|
|
|
|
|
|
|
as an argument so you can build data out of other data if you need to. See |
194
|
|
|
|
|
|
|
L for some examples of this. |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=head1 BUGS AND KNOWN ISSUES |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
There is no way to selectively remove data sources from a plugin that was |
199
|
|
|
|
|
|
|
loaded, even if you didn't load it. |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=head1 SEE ALSO |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
Text::Lorem |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=head1 AUTHOR |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
Jason Kohles, Eemail@jasonkohles.comE |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
Copyright 2004-2005 by Jason Kohles |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
214
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=cut |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
1; |