ACME-QuoteDB
view release on metacpan - search on metacpan
view release on metacpan or search on metacpan
#TODO give user choices about installing the quotes database
#i.e. location/permissions/owner, others?
use strict;
use warnings;
use Module::Build;
my $class = Module::Build->subclass(code => <<'EOF');
use File::Spec;
use File::Copy;
use File::Basename qw/dirname/;
META.yml
README
t/00-load.t
t/01-load_quotes.t
t/02-get_quotes.t
t/03-load_quotes_env.t
t/04-get_quotes_more.t
t/04-load_get_quote_utf8.t
t/05-load_quotes_remote.t
t/boilerplate.t
t/data/futurama
t/data/python_quotes.txt
t/data/simpsons_quotes.csv
t/data/simpsons_quotes.tsv.csv
t/data/utf8.csv
t/data/www.amk.ca/quotations/python-quotes/index.html
t/data/www.amk.ca/quotations/python-quotes/page-10.html
t/data/www.amk.ca/quotations/python-quotes/page-2.html
t/data/www.amk.ca/quotations/python-quotes/page-3.html
t/pod-coverage.t
t/pod.t
ACME-QuoteDB
ACME::QuoteDB â API implements CRUD for a Collection of Quotes
(adages/proverbs/sayings/epigrams, etc)
This module provides an easy to use programmitic interface to a dataâ
base (sqlite3 or mysql) of âquotesâ. (any content really, that can fit
into our "defined format")
For simplicty you can think of it as a modern fancy perl version of
fortune (with a management interface, remote database connection supâ
port, plus additional features and some not (yet) supported)
Supported actions include: (CRUD)
1 Create
* Adding quote(s)
* âBatchâ Loading quotes from a file (stream, other database, etc)
1 Read
* Displaying a single quote, random or based on some criteria
* Displaying multiple quotes, based on some criteria
* Displaying a specific number of quotes, based on some search criteria
1 Update
* Update an existing quote
1 Delete
lib/ACME/QuoteDB.pm view on Meta::CPAN
else {
if ($qc_obj->catg_id eq $catg_ids){
# use cat_id if already exists
push @{$quote_ids}, $qc_obj->quot_id;
}
}
}
return $quote_ids;
}
sub _untaint_data {
my ($arr_ref) = @_;
my $ut_ref = ();
foreach my $q (@{$arr_ref}){
if ($q =~ m{\A([0-9]+)\z}sm){
push @{$ut_ref}, $1;
}
}
return $ut_ref;
}
lib/ACME/QuoteDB/DB/quotedb/quotes.db matches view on Meta::CPAN
Also see t/01* included with the distribution.
(available from the CPAN if not included on your system)
=head1 SUBROUTINES/METHODS
see L<ACME::QuoteDB>
=head2 get_current_db_path
returns the path to our current database.
determined first by $ENV{ACME_QUOTEDB_PATH}
and next by the default system path to 'quotes.db'
=head1 DIAGNOSTICS
None currently known
=head1 CONFIGURATION AND ENVIRONMENT
By default, the quotes database used by this module installs in a system path,
which means you'll need to be root (sudo :) to load and modify it.
Alternativly, one can specify a location to a quotes database (file) to use.
Set the environmental variable:
$ENV{ACME_QUOTEDB_PATH} (untested on windows)
(this has to be set before trying a database load and also (everytime) before
using this module, obviouly)
see L<ACME::QuoteDB>
and
see L<ACME::QuoteDB::LoadDB>
=head1 DEPENDENCIES
lib/ACME/QuoteDB/LoadDB.pm view on Meta::CPAN
Readonly my @QUOTE_FIELDS => qw/quote name source catg rating/;
# XXX refactor
sub new {
my ($class, $args) = @_;
# TODO encapsulation
my $self = bless {}, $class;
# store each record we extract - keys map to database fields
# TODO proper encapsulation
$self->{record} = {};
$self->{record}->{quote} = q{};
$self->{record}->{rating} = q{};
$self->{record}->{name} = q{};
$self->{record}->{source} = q{};
$self->{record}->{catg} = q{};
$self->{file} = $args->{file};
$self->{dir} = $args->{dir};
$self->{data} = $args->{data};
$self->{file_format} = $args->{file_format};
$FILE_ENCODING = $args->{file_encoding} || $FILE_ENCODING;
$self->{delim} = $args->{delimiter};
$self->{verbose} = $args->{verbose};
$self->{category} = $args->{category};
$self->{rating} = $args->{rating};
$self->{attr_source} = $args->{attr_source};
$self->{orig_args} = $args;
$self->{success} = undef;
t/01-load_quotes.t view on Meta::CPAN
use ACME::QuoteDB;
use ACME::QuoteDB::LoadDB;
#use Test::More 'no_plan';
use Test::More tests => 29;
use File::Basename qw/dirname/;
use Data::Dumper qw/Dumper/;
use File::Spec;
# A. test dry run, show if parsing is succesful but don't load the database
{
my $q = File::Spec->catfile((dirname(__FILE__),'data'),
'simpsons_quotes.tsv.csv'
);
# only 2 supported formats: 'simple' text (which is the default) and 'tsv'
my $load_db = ACME::QuoteDB::LoadDB->new({
file => $q,
file_format => 'tsv', # the only supported format
delimiter => "\t",
# provide a category for all (if not in data)
category => 'Humor',
# provide a attr_source for all (if not in data)
attr_source => 'The Simpsons',
dry_run => 1, # don't write to the database
#verbose => 1, # show what is being done
create_db => 1, # need to create the database
});
isa_ok $load_db, 'ACME::QuoteDB::LoadDB';
$load_db->data_to_db;
#flag not set on dry_run
is $load_db->success, undef; # success only after a database write,
my $sq = ACME::QuoteDB->new;
isa_ok $sq, 'ACME::QuoteDB';
ok ! $sq->list_attr_names;
}
{
my $load_db = ACME::QuoteDB::LoadDB->new({
file =>
#dirname(__FILE__).'/data/simpsons_quotes.tsv.csv',
File::Spec->catfile(
(dirname(__FILE__),'data'),
'simpsons_quotes.tsv.csv'
),
file_format => 'tsv',
delimiter => "\t",
#verbose => 1,
create_db => 1, # first run, create the db
# provide a attr_source for all (if not in data)
attr_source => 'The Simpsons',
# provide a category for all (if not in data)
category => 'Humor',
# provide a rating for all
rating => 6,
});
isa_ok $load_db, 'ACME::QuoteDB::LoadDB';
$load_db->data_to_db;
ok $load_db->success;
is $load_db->success, 1;
my $sq = ACME::QuoteDB->new;
isa_ok $sq, 'ACME::QuoteDB';
# expected attribution list from our data
my @expected_attribution_list = (
'Apu Nahasapemapetilon',
'Chief Wiggum',
'Comic Book Guy',
'Grandpa Simpson',
'Ralph Wiggum',
);
is( $sq->list_attr_names, join "\n", sort @expected_attribution_list);
}
{
#my $sqf = dirname(__FILE__) . '/data/simpsons_quotes.csv';
my $sqf = File::Spec->catfile((dirname(__FILE__),'data'),
'simpsons_quotes.csv'
);
my $load_db = ACME::QuoteDB::LoadDB->new({
file => $sqf,
file_format => 'csv',
#delimiter => ",", # comma is default
#verbose => 1,
create_db => 1, # first run, create the db
});
isa_ok $load_db, 'ACME::QuoteDB::LoadDB';
$load_db->data_to_db;
ok $load_db->success;
is $load_db->success, 1;
my $sq = ACME::QuoteDB->new;
isa_ok $sq, 'ACME::QuoteDB';
# expected attribution list from our data
my @expected_attribution_list = (
'Apu Nahasapemapetilon',
'Chief Wiggum',
'Comic Book Guy',
'Grandpa Simpson',
'Ralph Wiggum',
);
is( $sq->list_attr_names, join("\n", sort(@expected_attribution_list)));
}
{ # load from html is not supported because there are too many
# ways to represt the data.
# this is an example of extracting quotes from html:
# subclass ACME::QuoteDB::LoadDB and override dbload,
# to do our html parsing
package LoadQuoteDBFromHtml;
use base 'ACME::QuoteDB::LoadDB';
use Carp qw/croak/;
use Data::Dumper qw/Dumper/;
use HTML::TokeParser;
sub dbload {
my ($self, $file) = @_;
my $p = HTML::TokeParser->new($file) || croak $!;
while (my $token = $p->get_tag("p")) {
my $idn = $token->[1]{class} || q{};
my $id = $token->[1]{id} || q{}; # if a quotation is continued (id
#is not set)
next unless $idn and ( $idn eq 'quotation' || $idn eq 'source');
#my $data = $p->get_trimmed_text("/p");
my $data = $p->get_text('p', 'cite');
#warn Dumper $data;
# XXX see $self->set_record in ACME::QuoteDB::LoadDB for fields
# to populate
if ($idn eq 'quotation' and $id) {
$self->set_record(quote => $data);
}
elsif ($idn eq 'quotation' and not $id) {
my $d = $self->get_record('quote') || q{};
$self->set_record(quote => qq{$d $data});
}
elsif ($idn eq 'source'){
my ($name, $source) = split /,/, $data;
if ($name) {
chomp $name;
$name =~ s/\A\s+//xms;
$name =~ s/\s+\z//xms;
}
$self->set_record(name => $name);
$self->set_record(source => $source);
# TODO
#$self->set_record({
# name => $name,
# source => $source
#});
}
if ($self->get_record('quote') and $self->get_record('name')) {
# we provided a category and rating, otherwise would have to
# parse from data too
$self->set_record(catg => $self->{category});
$self->set_record(rating => $self->{rating});
# TODO
#$self->set_record({
# catg => $self->{category},
# rating => $self->{rating}
#});
#$self->debug_record;
t/02-get_quotes.t view on Meta::CPAN
sub make_test_db_rw {
use ACME::QuoteDB::DB::DBI;
# yeah, this is supposed to be covered by the build process
# but is failing sometimes,...
chmod 0666, ACME::QuoteDB::DB::DBI->get_current_db_path;
}
{
make_test_db_rw;
my $q = File::Spec->catfile((dirname(__FILE__),'data'), 'simpsons_quotes.csv');
my $load_db = ACME::QuoteDB::LoadDB->new({
file => $q,
file_format => 'csv',
create_db => 1, # first run, create the db
});
isa_ok $load_db, 'ACME::QuoteDB::LoadDB';
$load_db->data_to_db;
is $load_db->success, 1;
}
my $sq = ACME::QuoteDB->new;
# some 'the simpsons' characters
my @expected_attr_name_list = (
'Apu Nahasapemapetilon',
'Chief Wiggum',
'Comic Book Guy',
t/03-load_quotes_env.t view on Meta::CPAN
ok unlink $def_db;
}
else {
ok 'already gone';
}
}
ok -z $ENV{ACME_QUOTEDB_PATH};
{
my $q = File::Spec->catfile((dirname(__FILE__),'data'),
'simpsons_quotes.tsv.csv'
);
my $load_db = ACME::QuoteDB::LoadDB->new({
file => $q,
file_format => 'tsv',
create_db => 1,
delimiter => "\t",
attribution => 'The Simpsons',
category => 'Humor',
rating => 6,
#verbose =>1
});
isa_ok $load_db, 'ACME::QuoteDB::LoadDB';
$load_db->data_to_db;
ok $load_db->success;
is $load_db->success, 1;
my $sq = ACME::QuoteDB->new;
isa_ok $sq, 'ACME::QuoteDB';
# expected attribution list from our data
my @expected_attribution_list = (
'Apu Nahasapemapetilon',
'Chief Wiggum',
'Comic Book Guy',
'Grandpa Simpson',
'Ralph Wiggum',
);
is( $sq->list_attr_names, join "\n", sort @expected_attribution_list);
t/04-get_quotes_more.t view on Meta::CPAN
"\nPeter: Drank at the stag pa-- ... Whoa. I almost walked into that one.";
{
#make test db writeable
use ACME::QuoteDB::DB::DBI;
# yeah, this is supposed to be covered by the build process
# but is failing sometimes,...
chmod 0666, ACME::QuoteDB::DB::DBI->get_current_db_path;
my $q = File::Spec->catfile((dirname(__FILE__),'data'),
'simpsons_quotes.csv'
);
my $load_db = ACME::QuoteDB::LoadDB->new({
file => $q,
file_format => 'csv',
create_db => 1,
});
isa_ok $load_db, 'ACME::QuoteDB::LoadDB';
$load_db->data_to_db;
is $load_db->success, 1;
}
my $sq = ACME::QuoteDB->new;
is $sq->get_quote({Rating => '8.7'}),
"Me fail English? That's unpossible.\n-- Ralph Wiggum";
is( $sq->list_attr_sources, 'The Simpsons');
is( $sq->list_categories, 'Humor');
t/04-load_get_quote_utf8.t view on Meta::CPAN
$@ and croak 'DBD::SQLite is a required dependancy';
# give alternate path to the DB
$ENV{ACME_QUOTEDB_PATH} =
File::Temp->new( UNLINK => 0,
EXLOCK => 0,
SUFFIX => '.dat',
);
}
# matches the data in our utf8.csv file, soon to be in our quote db
my $utf8_quotes = [
'¥ · £ · â¬Â · $ · ¢ · â¡Â · â¢Â · â£Â · â¤Â · â¥Â · â¦Â · â§Â · â¨Â · â©Â · âªÂ · â«Â · â · â®Â · â¯',
'æè½åä¸ç»çèä¸ä¼¤èº«ä½ã',
'ç§ã¯ã¬ã©ã¹ãé£ã¹ããã¾ããããã¯ç§ãå·ã¤ãã¾ããã',
'ëë ì 리를 먹ì ì ìì´ì. ê·¸ëë ìíì§ ììì',
'Tsésǫʼ yishÄ
ÌÄ
go bÃÃnÃshghah dóó doo shiÅ neezgai da. ',
'ÎÏοÏÏ Î½Î± ÏÎ¬Ï ÏÏαÏμÎνα γÏ
αλιά ÏÏÏÎ¯Ï Î½Î± ÏÎ¬Î¸Ï ÏίÏοÏα.',
'मà¥à¤ à¤à¤¾à¤à¤ à¤à¤¾ सà¤à¤¤à¤¾ हà¥à¤, मà¥à¤à¥ à¤à¤¸ सॠà¤à¥à¤ पà¥à¤¡à¤¾ नहà¥à¤ हà¥à¤¤à¥.',
'×× × ×××× ××××× ×××××ת ××× ×× ××××§ ××',
];# any takers for specifying each multibyte code sequence for the above,.. ;)
{
#make test db writeable
use ACME::QuoteDB::DB::DBI;
# yeah, this is supposed to be covered by the build process
# but is failing sometimes,...
chmod 0666, ACME::QuoteDB::DB::DBI->get_current_db_path;
my $q = File::Spec->catfile((dirname(__FILE__),'data'),
'utf8.csv'
);
my $load_db = ACME::QuoteDB::LoadDB->new({
file => $q,
file_format => 'csv',
delimiter => "\t",
create_db => 1
});
isa_ok $load_db, 'ACME::QuoteDB::LoadDB';
$load_db->data_to_db;
is $load_db->success, 1;
}
my $sq = ACME::QuoteDB->new;
# matches the data in our utf8.csv file, attribution's to the 'quotes' above
my @expected_attribution_list = (
'UTF-8 Sampler Currency',
'I can eat grass (Chinese)',
'I can eat grass (Japanese)',
'I can eat grass (Korean)',
'I can eat grass (Navajo)',
'I can eat grass (Greek)',
'I can eat grass (Hindi)',
'I can eat grass (Hebrew)',
);
t/05-load_quotes_remote.t view on Meta::CPAN
#use Test::More qw/no_plan/;
use File::Basename qw/dirname/;
use DBI;
use File::Temp;
use File::Spec;
BEGIN {
eval "use DBI";
$@ and plan skip_all => 'DBI/mysql is required for this test';
# have to set this to use remote database
$ENV{ACME_QUOTEDB_REMOTE} = 'mysql';
$ENV{ACME_QUOTEDB_DB} = 'acme_quotedb';
$ENV{ACME_QUOTEDB_HOST} = 'localhost';
$ENV{ACME_QUOTEDB_USER} = 'acme_user';
$ENV{ACME_QUOTEDB_PASS} = 'acme';
}
my $database = $ENV{ACME_QUOTEDB_DB};
my $host = $ENV{ACME_QUOTEDB_HOST};
my $user = $ENV{ACME_QUOTEDB_USER};
my $pass = $ENV{ACME_QUOTEDB_PASS};
# XXX these use's must happen after the BEGIN,...
use ACME::QuoteDB::LoadDB;
use ACME::QuoteDB;
eval {
my $q = File::Spec->catfile((dirname(__FILE__),'data'),
'simpsons_quotes.csv'
);
my $load_db = ACME::QuoteDB::LoadDB->new({
file => $q,
file_format => 'csv',
create_db => 1,
});
};
$@ and plan skip_all => 'mysql not installed or not configured for test user';
# ok, still here? let's run some tests
plan tests => 7;
{ # create it
my $q = File::Spec->catfile((dirname(__FILE__),'data'),
'simpsons_quotes.csv'
);
my $load_db = ACME::QuoteDB::LoadDB->new({
file => $q,
file_format => 'csv',
create_db => 1,
});
isa_ok $load_db, 'ACME::QuoteDB::LoadDB';
$load_db->data_to_db;
ok $load_db->success;
is $load_db->success, 1;
my $sq = ACME::QuoteDB->new;
isa_ok $sq, 'ACME::QuoteDB';
# expected attribution list from our data
my @expected_attribution_list = (
'Apu Nahasapemapetilon',
'Chief Wiggum',
'Comic Book Guy',
'Grandpa Simpson',
'Ralph Wiggum',
);
is( $sq->list_attr_names, join "\n", sort @expected_attribution_list);
$load_db = undef;
}
my $dbh = DBI->connect("DBI:mysql:database=$database;host=$host",$user,$pass)
|| croak "can not connect to: $database $!";
my $count = $dbh->selectrow_hashref('SELECT COUNT(*) AS COUNT FROM quote');
is $count->{COUNT}, 29 ;
my $qc = $dbh->selectrow_hashref('SELECT COUNT(*) AS COUNT FROM quote_catg');
is $qc->{COUNT}, 29 ;
t/data/python_quotes.txt view on Meta::CPAN
... we need more people like him, who are willing to explore without being
driven to argue with people about it.
-- William Tanksley on Chuck Moore, inventor of Forth, 2 Jul 1999
Sorry for the term, I picked it up from Jim Fulton back when it was an
about-to-be-added feature for Principia/Aqueduct. As with so many Fultonisms,
it's vivid and tends to stick in one's (non-pluggable) brain.
-- Paul Everitt on the term "pluggable brains", 5 Jul 1999
I picture a lump of inanimate flesh (a result from a relational database query)
being infused with the spark of life (object behavior, aka class).
-- Jim Fulton on the term "pluggable brains", 5 Jul 1999
This is good. It means that while Ionesco is dead, his spirit lives on.
-- Gordon McMillan on how Windows attaches meaning to 3-character
file extensions, 30 Jul 1999
(On the statement print "42 monkeys"+"1 snake") BTW, both Perl and Python get
this wrong. Perl gives 43 and Python gives "42 monkeys1 snake", when the answer
is clearly "41 monkeys and 1 fat snake".
view all matches for this distributionview release on metacpan - search on metacpan
( run in 0.707 second using v1.00-cache-2.02-grep-82fe00e-cpan-4673cadbf75 )