view release on metacpan or search on metacpan
0.1.2 Wed Sep 30 23:26:11 PDT 2009
bug fixes:
* Build.PL install changes - SQLite3 could not actually write to the database,
even though, the db file was world writeable. The container dir
also needs to be writable, now it is.
* ensure the database is 0666 for tests as well
0.1.1 Fri Sep 18 02:11:02 PDT 2009
bug fixes:
* default constructor values were not getting set on the object as they should
* loosen untaint filepath - for the dist test failures
0.1.0 Wed Sep 9 23:43:56 PDT 2009
Initial public pre-release (minor version)
lib/ACME/QuoteDB.pm view on Meta::CPAN
#$Id: QuoteDB.pm,v 1.36 2009/09/30 07:37:09 dinosau2 Exp $
# /* vim:et: set ts=4 sw=4 sts=4 tw=78: */
package ACME::QuoteDB;
use 5.008005; # require perl 5.8.5, re: DBD::SQLite Unicode
use warnings;
use strict;
#major-version.minor-revision.bugfix
use version; our $VERSION = qv('0.1.2');
lib/ACME/QuoteDB.pm view on Meta::CPAN
sub add_quote {
my ( $self, $arg_ref ) = @_;
_args_are_valid($arg_ref, [qw/Quote AttrName Source Rating Category/]);
my $load_db = ACME::QuoteDB::LoadDB->new({
#verbose => 1,
});
$load_db->set_record(quote => $arg_ref->{Quote});
$load_db->set_record(name => $arg_ref->{AttrName});
$load_db->set_record(source => $arg_ref->{Source});
$load_db->set_record(catg => $arg_ref->{Category});
$load_db->set_record(rating => $arg_ref->{Rating});
if ($load_db->get_record('quote') and $load_db->get_record('name')) {
return $load_db->write_record;
}
else {
croak 'quote and attribution name are mandatory parameters';
}
return;
}
lib/ACME/QuoteDB.pm view on Meta::CPAN
foreach my $q ( @{$sq->get_quotes({Limit => 6})} ) {
print "$q\n";
}
# get list of available attributions (that have quotes provided by this module)
print $sq->list_attr_names;
# any unique part of name will work
# i.e these will all return the same results (because of our limited
# quotes db data set)
print $sq->get_quotes({AttrName => 'comic book guy'});
print $sq->get_quotes({AttrName => 'comic book'});
print $sq->get_quotes({AttrName => 'comic'});
print $sq->get_quotes({AttrName => 'book'});
print $sq->get_quotes({AttrName => 'book guy'});
print $sq->get_quotes({AttrName => 'guy'});
# get all quotes, only using these categories (you have defined)
print @{$sq->get_quotes({ Category => [qw(Humor ROTFLMAO)] })};
lib/ACME/QuoteDB.pm view on Meta::CPAN
"I hope this has taught you kids a lesson: kids never learn.","Chief Wiggum","The Simpsons","Humor",9
"Sideshow Bob has no decency. He called me Chief Piggum. (laughs) Oh wait, I get it, he's all right.","Chief Wiggum","The Simpsons","Humor",8
=item 1 if these dont suit your needs, ACME::QuoteDB::LoadDB is sub-classable,
so one can extract data anyway they like and populate the db themselves.
(there is a test that illustrates overriding the stub method, 'dbload')
you need to populate a record data structure:
$self->set_record(quote => q{}); # mandatory
$self->set_record(name => q{}); # mandatory
$self->set_record(source => q{}); # optional but useful
$self->set_record(catg => q{}); # optional but useful
$self->set_record(rating => q{}); # optional but useful
# then to write the record you call
$self->write_record;
NOTE: this is a record-by-record operation, so one would perform this within a
loop. there is no bulk (memory dump) write operation currently.
=back
lib/ACME/QuoteDB.pm view on Meta::CPAN
install cpan modules, you should have no problem installing this module
(utf-8 support in DBD::SQLite not avaible until 5.8 - we don't support 'non
utf-8 mode)
=over 1
=item * By default, the quotes database used by this module installs in the
system path, 'lib', (See L<Module::Build/"INSTALL PATHS">)
as world writable - i.e. 0666 (and probably owned by root)
If you don't like this, you can modify Build.PL to not chmod the file and it
will install as 444/readonly, you can also set a chown in there for whoever
you want to have RW access to the quotes db.
Alternativly, one can specify a location to a quotes database (file) to use.
(Since the local mode is sqlite3, the file doesn't even need to exist, just
needs read/write access to the path on the filesystem)
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)
Something such as:
BEGIN {
# give alternate path to the DB
# doesn't need to exist, will create
$ENV{ACME_QUOTEDB_PATH} = '/home/me/my_stuff/my_quote_db'
}
* (NOTE: be sure this (BEGIN) exists *before* the 'use ACME::QuoteDB' lines)
The default is to use sqlite3.
In order to connect to a mysql database, several environmental variables
are required.
BEGIN {
# 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';
}
Set the above in a begin block.
The database connection is transparent.
lib/ACME/QuoteDB.pm view on Meta::CPAN
XXX - look at search_like, instead of what you are doing now
=end comment
currently, I am not encapsulating the record data structure used
by LoadDB->write. (i.e. it's a typical perl5 ojbect, the blessed hash)
I will for sure be encapsulating all data in a future version.
(so, don't have code that does $self->{record}->{name} = 'value', or you won't
be happy down the road). Instead use $self->get_record('name') (getter) or
$self->set_record(name => 'my attrib') (setter)
When we are using a SQLite database backend ('regular' local usage), we
should probably be using, ORLite instead of Class::DBI
(although we have not seen any issues yet).
Please report any bugs or feature requests to C<bug-acme-quotedb at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=ACME-QuoteDB>.
I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
lib/ACME/QuoteDB/DB/Attribution.pm view on Meta::CPAN
#$Id: Attribution.pm,v 1.12 2009/09/30 07:37:09 dinosau2 Exp $
# /* vim:et: set ts=4 sw=4 sts=4 tw=78: */
package ACME::QuoteDB::DB::Attribution;
use base 'ACME::QuoteDB::DB::DBI';
use 5.008005; # require perl 5.8.5, re: DBD::SQLite Unicode
use warnings;
use strict;
#use criticism 'brutal'; # use critic with a ~/.perlcriticrc
lib/ACME/QuoteDB/DB/Category.pm view on Meta::CPAN
#$Id: Category.pm,v 1.7 2009/09/30 07:37:09 dinosau2 Exp $
# /* vim:et: set ts=4 sw=4 sts=4 tw=78: */
package ACME::QuoteDB::DB::Category;
use base 'ACME::QuoteDB::DB::DBI';
use 5.008005; # require perl 5.8.5, re: DBD::SQLite Unicode
use warnings;
use strict;
#use criticism 'brutal'; # use critic with a ~/.perlcriticrc
lib/ACME/QuoteDB/DB/DBI.pm view on Meta::CPAN
#$Id: DBI.pm,v 1.19 2009/09/30 07:37:09 dinosau2 Exp $
# /* vim:et: set ts=4 sw=4 sts=4 tw=78: */
package ACME::QuoteDB::DB::DBI;
use base 'Class::DBI';
use 5.008005; # require perl 5.8.5
# DBD::SQLite Unicode is not supported before 5.8.5
use warnings;
use strict;
#use criticism 'brutal'; # use critic with a ~/.perlcriticrc
lib/ACME/QuoteDB/DB/DBI.pm view on Meta::CPAN
use File::Basename qw/dirname/;
use Carp qw/croak/;
use Cwd 'abs_path';
use File::Spec;
Readonly my $QUOTES_DATABASE => $ENV{ACME_QUOTEDB_PATH}
|| File::Spec->catfile(_untaint_db_path(),
q(quotedb), q(quotes.db)
);
# set this to use a remote database
# i.e. mysql
Readonly my $REMOTE => $ENV{ACME_QUOTEDB_REMOTE};
# be more specific (or more general) this is mysql
# and 'remote' can be localhost
if ($REMOTE && $REMOTE ne 'mysql') {
croak "mysql is the only remote database supported"
." set ENV{ACME_QUOTEDB_REMOTE} = 'mysql'";
}
elsif ($REMOTE && $REMOTE eq 'mysql') {
my $database = $ENV{ACME_QUOTEDB_DB};
my $host = $ENV{ACME_QUOTEDB_HOST};
my $user = $ENV{ACME_QUOTEDB_USER};
my $pass = $ENV{ACME_QUOTEDB_PASS};
ACME::QuoteDB::DB::DBI->connection(
"DBI:mysql:database=$database;host=$host",$user,$pass,
lib/ACME/QuoteDB/DB/DBI.pm view on Meta::CPAN
# func/pragma's may not work here,..(probably isnt' smart anyway)
#count_changes => 0,
#temp_store => 2,
#synchronous => 'OFF',
#busy_timeout => 3600000
}
)
|| croak "$QUOTES_DATABASE does not exist, or cant be created $!";
# how to enable this function?
#ACME::QuoteDB::DB::DBI->set_sql(func( 3600000, 'busy_timeout' );
}
sub get_current_db_path {
return $QUOTES_DATABASE;
}
sub _untaint_db_path {
my $sane_path = abs_path(dirname(__FILE__));
# appease taint mode, what a dir path looks like,... (probably not)
lib/ACME/QuoteDB/DB/DBI.pm view on Meta::CPAN
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/DB/Quote.pm view on Meta::CPAN
#$Id: Quote.pm,v 1.12 2009/09/30 07:37:09 dinosau2 Exp $
# /* vim:et: set ts=4 sw=4 sts=4 tw=78: */
package ACME::QuoteDB::DB::Quote;
use base 'ACME::QuoteDB::DB::DBI';
use 5.008005; # require perl 5.8.5, re: DBD::SQLite Unicode
use warnings;
use strict;
#use criticism 'brutal'; # use critic with a ~/.perlcriticrc
lib/ACME/QuoteDB/DB/QuoteCatg.pm view on Meta::CPAN
#$Id: QuoteCatg.pm,v 1.4 2009/09/30 07:37:09 dinosau2 Exp $
# /* vim:et: set ts=4 sw=4 sts=4 tw=78: */
package ACME::QuoteDB::DB::QuoteCatg;
use base 'ACME::QuoteDB::DB::DBI';
use 5.008005; # require perl 5.8.5, re: DBD::SQLite Unicode
use warnings;
use strict;
#use criticism 'brutal'; # use critic with a ~/.perlcriticrc
lib/ACME/QuoteDB/LoadDB.pm view on Meta::CPAN
#$Id: LoadDB.pm,v 1.30 2009/09/30 07:37:09 dinosau2 Exp $
# /* vim:et: set ts=4 sw=4 sts=4 tw=78: */
package ACME::QuoteDB::LoadDB;
use 5.008005; # require perl 5.8.5, re: DBD::SQLite Unicode
use warnings;
use strict;
#use criticism 'brutal'; # use critic with a ~/.perlcriticrc
use version; our $VERSION = qv('0.1.1');
lib/ACME/QuoteDB/LoadDB.pm view on Meta::CPAN
$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;
# start with if set
$self->{record}->{rating} = $self->{rating};
$self->{record}->{name} = $self->{attr_source};
$self->{record}->{source} = $self->{attr_source};
if (ref $self->{category} eq 'ARRAY') {
$self->{record}->{catg} = ();
foreach my $c (@{$self->{category}}){
push @{$self->{record}->{catg}}, $c;
}
}
else {
lib/ACME/QuoteDB/LoadDB.pm view on Meta::CPAN
$self->{pass} = $ENV{ACME_QUOTEDB_PASS};
}
if (!$args->{dry_run}){$self->{write_db} = 1};
#if ($args->{create_db}) {$self->create_db};
if ($args->{create_db}) {$self->create_db_tables};
return $self;
}
sub set_record {
my ($self, $field, $value) = @_;
# TODO support mult-field simultanous loading
if ($value) {
$self->{record}->{$field} = $value;
}
return $self;
}
lib/ACME/QuoteDB/LoadDB.pm view on Meta::CPAN
if ($self->{verbose}){
print "\n",
'Quote: ', $hr->{quote},"\n",
'Name: ', $hr->{name},"\n",
'Source: ', $hr->{source},"\n",
'Category:', $hr->{catg},"\n",
'Rating: ', $hr->{rating},"\n\n";
};
$self->set_record(quote => $hr->{quote});
$self->set_record(name => $hr->{name});
$self->set_record(source => ($self->{attr_source} || $hr->{source}));
# take user defined first
# TODO support multi categories
$self->set_record(catg => ($self->{category} || $hr->{catg}));
$self->set_record(rating => ($self->{rating} || $hr->{rating}));
$self->write_record;
}
close $source or carp $!;
return $self;
}
# sub class this - i.e. provide this method in your code (see test
# 01-load_quotes.t)
sub dbload {
lib/ACME/QuoteDB/LoadDB.pm view on Meta::CPAN
quot_id => $qid,
catg_id => $cid,
}) or croak $!;
}
}
}
# confirmation?
# TODO add a test for failure
if ($self->{write_db} and not $attr_id) {croak 'db write not successful'}
#$self->set_record(undef);
$self->{record} = {};
$self->_reset_orig_args;
if ($self->{write_db}) {
$self->success(1);
}
return $self->success;
}
sub _reset_orig_args {
my ($self) = @_;
$self->{record}->{rating} = $self->{orig_args}->{rating};
$self->{record}->{name} = $self->{orig_args}->{attr_source};
$self->{record}->{source} = $self->{orig_args}->{attr_source};
if (ref $self->{orig_args}->{category} eq 'ARRAY') {
foreach my $c (@{$self->{orig_args}->{category}}){
push @{$self->{record}->{catg}}, $c;
}
}
lib/ACME/QuoteDB/LoadDB.pm view on Meta::CPAN
=head3 load from any source
If those dont catch your interest, ACME::QuoteDB::LoadDB is sub-classable,
so one can extract data anyway they like and populate the db themselves.
(there is a test that illustrates overriding the stub method, 'dbload')
you need to populate a record data structure:
$self->set_record(quote => q{}); # mandatory
$self->set_record(name => q{}); # mandatory
$self->set_record(source => q{}); # optional but useful
$self->set_record(catg => q{}); # optional but useful
$self->set_record(rating => q{}); # optional but useful
# then to write the record you call
$self->write_record;
NOTE: this is a one record at a time operation, so one would perform
this within a loop. there is no bulk write operation currently.
=head1 OVERVIEW
lib/ACME/QuoteDB/LoadDB.pm view on Meta::CPAN
=item attr_source - extracted from data if exists, otherwise will use what you
specify
example:
{attr_source => 'The Simpsons'}
=item file_encoding - optional
Files being loaded are assumed to be utf8 encoded. if utf8 flag is not detected,
falls back to latin1 (iso-8859-1). If neither of these is correct, set this
option to the encoding your file is in.
=back
=head4 Operation Related Parameters
=over 4
=item dry_run - optional
lib/ACME/QuoteDB/LoadDB.pm view on Meta::CPAN
example:
{verbose => 1}
=item create_db - optional (boolean)
L<ACME::QuoteDB::LoadDB> default behaviour is to always assume there is a
database and append new data to that. (It is usually only needed the first
time one load's data)
setting this parameter to a true value will create a new database.
(so while this is an optional param, it is required at least once ;)
B<NOTE: it is not intelligent, if you hand it a populated database,
it will happily overwrite all data>
B<AGAIN: setting this param will destroy the current database, creating a new
empty one>
example:
{create_db => 1}
=back
=head2 data_to_db
lib/ACME/QuoteDB/LoadDB.pm view on Meta::CPAN
takes a csv file (in our defined format) as an argument, parses it and writes
the data to the database. (uses L<Text::CSV> with pure perl parser)
utf-8 safe. (opens file as utf8)
will croak with message if not successful
=head2 dbload
if your file format is set to 'html' or 'custom' you must
define this method to do your parsing in a sub class.
Load from html is not supported because there are too many
ways to represt the data. (same with 'custom')
(see tests for examples - there is a test for loading a 'fortune' file format)
One can subclass ACME::QuoteDB::LoadDB and override dbload,
to do our html parsing
=head2 debug_record
dump record (show what is set on the internal data structure)
e.g. Data::Dumper
=head2 set_record
only needed it one plans to sub-class this module.
otherwise, is transparent in usage.
if you are sub-classing this module, you would have to populate
this record. (L</write_record> knows about/uses this data structure)
possible fields consist of:
$self->set_record(quote => q{});
$self->set_record(rating => q{});
$self->set_record(name => q{});
$self->set_record(source => q{});
$self->set_record(catg => q{});
currently can only set one attribute at a time.
ie. you cant do this:
$self->set_record(
name => $name,
source => $source
);
# or this even
$self->set_record({
name => $name,
source => $source
});
=head2 get_record
only useful it one plans to sub-class this module.
otherwise, is transparent in usage.
if you are sub-classing this module, you would have to populate
this record. [see L</set_record>]
(L</write_record> knows about/uses this data structure)
possible fields consist of:
$self->get_record('quote');
$self->get_record('rating');
$self->get_record('name');
$self->get_record('source');
$self->get_record('catg');
lib/ACME/QuoteDB/LoadDB.pm view on Meta::CPAN
install cpan modules, you should have no problem installing this module
(utf-8 support in Text::CSV not avaible until 5.8 - we don't support 'non
utf-8 mode)
=over 1
=item * By default, the quotes database used by this module installs in the
system path, 'lib', (See L<Module::Build/"INSTALL PATHS">)
as world writable - i.e. 0666 (and probably owned by root)
If you don't like this, you can modify Build.PL to not chmod the file and it
will install as 444/readonly, you can also set a chown in there for whoever
you want to have RW access to the quotes db.
Alternativly, one can specify a location to a quotes database (file) to use.
(Since the local mode is sqlite3, the file doesn't even need to exist, just
needs read/write access to the path)
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)
Something such as:
BEGIN {
# give alternate path to the DB
# doesn't need to exist, will create
$ENV{ACME_QUOTEDB_PATH} = '/home/me/my_stuff/my_quote_db'
}
* (NOTE: be sure this (BEGIN) exists *before* the 'use ACME::QuoteDB' lines)
The default is to use sqlite3.
In order to connect to a mysql database, several environmental variables
are required.
BEGIN {
# 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';
}
Set the above in a begin block and all operations are the same but now
you will be writing to the remote mysql database specified.
t/01-load_quotes.t view on Meta::CPAN
# 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 =>
t/01-load_quotes.t view on Meta::CPAN
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;
$self->write_record;
}
}
}
t/01-load_quotes.t view on Meta::CPAN
while (my $line = <$source>){
#$self->debug_record;
$q .= $line;
$q =~ s{\A\s+}{}xsmg;
$q =~ s{\s+\z}{}xsmg;
$q =~ s/\s+$self->{delim}//g;
$self->set_record(quote => $q);
my $name = $self->get_record('quote');
$name =~ s{\A(.*?):.*}{$1}xmsg; # not accurate,
$self->set_record(name => $name);
$self->set_record(source => $self->{attr_source});
$self->set_record(catg => $self->{category} || q{});
$self->set_record(rating => $self->{rating} || q{});
$self->write_record;
$q = q{};
}
close $source || croak $!;
}
package main;
use File::Basename qw/dirname/;
use File::Spec;
t/01-load_quotes.t view on Meta::CPAN
my $sq = ACME::QuoteDB->new;
isa_ok $sq, 'ACME::QuoteDB';
is( $sq->list_attr_sources, 'Futurama');
is( $sq->list_categories, 'Humor');
is scalar @{$sq->get_quotes({AttrName => 'Leela'})}, 2;
is scalar @{$sq->get_quotes({AttrName => 'Professor'})}, 2;
is scalar @{$sq->get_quotes({AttrName => 'Fry'})}, 4;
is scalar @{$sq->get_quotes({AttrName => 'Bender'})}, 1;
is scalar @{$sq->get_quotes({AttrName => 'Zapp'})}, 1;
# set_quote? update futurama to be in humor and cartoon
}
t/04-load_get_quote_utf8.t view on Meta::CPAN
#!perl -T
# /* vim:et: set ts=4 sw=4 sts=4 tw=78 encoding=utf-8: */
use 5.008005; # require perl 5.8.5
# DBD::SQLite Unicode is not supported before 5.8.5
use strict;
use warnings;
use utf8; # yes this source code does contain utf8 characters
use ACME::QuoteDB;
use ACME::QuoteDB::LoadDB;
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};
t/data/python_quotes.txt view on Meta::CPAN
Two things I learned for sure during a particularly intense acid trip in my own
lost youth: (1) everything is a trivial special case of something else; and,
(2) death is a bunch of blue spheres.
-- Tim Peters, 1 May 1998
Well, they will be: "<" will mean what everyone thinks it means when applied to
builtin types, and will mean whatever __lt__ makes it mean otherwise, except
when __lt__ isn't defined but __cmp__ is in which case it will mean whatever
__cmp__ makes it mean, except when neither __lt__ or __cmp__ are defined in
which case it's still unsettled. I think. Or isn't that what you meant by
"clearly defined"?
-- Tim Peters, 6 May 1998
You write a great program, regardless of language, by redoing it over & over &
over & over, until your fingers bleed and your soul is drained. But if you tell
newbies *that*, they might decide to go off and do something sensible, like
bomb defusing<wink>.
-- Tim Peters, 5 Jun 1998
OO styles help in part because they make it easier to redo large parts over,
t/data/python_quotes.txt view on Meta::CPAN
mind-if-i-use-that-as-my-epitaph<wink>?-ly y'rs - tim
-- Timothy J. Grant and Tim Peters, 22 Jun 1998
> Just for the record, on AIX, the following C program:
Oh no you don't! I followed AIX threads for the first year it came out, but
eventually decided there was no future in investing time in baffling
discussions that usually ended with "oh, never mind -- turns out it's a bug"
<0.9 wink>.
-- Vladimir Marangozov and Tim Peters, 23 Jun 1998
Python - why settle for snake oil when you can have the *whole* snake?
-- Mark Jackson, 26 Jun 1998
The problem I have with "SETL sets" in Python is the same I have with every
other language's "killer core" in Python: SETL is much more than just "a set
type", Eiffel is much more than just fancy pre- and post- conditions, Perl's
approach to regexps is much more than just its isolated regexp syntax, Scheme
is much more than just first-class functions & lexical closures, and so on.
Good languages aren't random collections of interchangeable features: they have
a philosophy and internal coherence that's never profitably confused with their
surface features.
-- Tim Peters, 10 Jul 1998
"Since I'm so close to the pickle module, I just look at the pickles
directly, as I'm pretty good at reading pickles."
t/data/python_quotes.txt view on Meta::CPAN
facilitator of/participant in online communities, better and more easily than I
otherwise could do.
-- Ken Manheimer, 24 Jan 1999
Every standard applies to a certain problem domain and a certain level. A
standard can work perfectly and save the world economy billions of dollars and
there will still be software and hardware compatibility problems. In fact,
solving one level of compatibility just gives rise to the next level of
incompatibility. For example, connecting computers together through standard
protocols gives rise to the problem of byte endianness issues. Solving byte
endianness gives rise to the problem of character sets. Solving character sets
gives rise to the problem of end-of-line and end-of-file conventions. Solving
that gets us to the problem of interpreting the low-level syntax (thus XML).
Then we need to interpet that syntax in terms of objects and properties (thus
RDF, WDDX, etc.). And so forth.
We could judge a standard's success by its ability to reveal another level
of standardization that is necessary.
-- Paul Prescod, 24 Jan 1999
I just want to go on the record as being completely opposed to computer
languages. Let them have their own language and soon they'll be off in the
t/data/python_quotes.txt view on Meta::CPAN
"XML applications" and "XML parsers" which handle this gang- of-four concepts.
... Now we can peer over the parapet and shout "your parser smells of
elderberries" or "I wave my mixed content at your ankles", as long as we like
but the simple gang-of-four base apps will not go away.
-- Sean McGrath, 19 Dec 1999
Abstraction is one of those notions that Python tosses out the window, yet
expresses very well.
-- Gordon McMillan, 6 Jan 2000
The set of naming conventions has a cardinality equal to the number of Python
users.
-- Gordon McMillan, 6 Jan 2000
The way to build large Python applications is to componentize and
loosely-couple the hell out of everything.
-- Aahz Maruch, 6 Jan 2000
It's not the mail volume that bothers me -- I can ignore 100s of messages a day
very quickly. It's the time it takes to respond to all of them.
-- Guido van Rossum, 20 Jan 2000
t/data/www.amk.ca/quotations/python-quotes/page-3.html view on Meta::CPAN
<p class='quotation' id='q66'>Two things I learned for sure during
a particularly intense acid trip in my own lost youth: (1)
everything is a trivial special case of something else; and, (2)
death is a bunch of blue spheres.</p>
<p class='source'>Tim Peters, 1 May 1998</p>
<p class='quotation' id='q67'>Well, they will be: "<" will mean
what everyone thinks it means when applied to builtin types, and
will mean whatever __lt__ makes it mean otherwise, except when
__lt__ isn't defined but __cmp__ is in which case it will mean
whatever __cmp__ makes it mean, except when neither __lt__ or
__cmp__ are defined in which case it's still unsettled. I think. Or
isn't that what you meant by "clearly defined"?</p>
<p class='source'>Tim Peters, 6 May 1998</p>
<p class='quotation' id='q68'>You write a great program, regardless
of language, by redoing it over & over & over & over,
until your fingers bleed and your soul is drained. But if you tell
newbies <em>that</em>, they might decide to go off and do something
sensible, like bomb defusing<wink>.</p>
<p class='source'>Tim Peters, 5 Jun 1998</p>
<p class='quotation' id='q69'>OO styles help in part because they
make it easier to redo large parts over, or, when the moon is
t/data/www.amk.ca/quotations/python-quotes/page-3.html view on Meta::CPAN
mind-if-i-use-that-as-my-epitaph<wink>?-ly y'rs - tim</p>
<p class='source'>Timothy J. Grant and Tim Peters, 22 Jun 1998</p>
<p class='quotation' id='q77'>> Just for the record, on AIX, the
following C program:
Oh no you don't! I followed AIX threads for
the first year it came out, but eventually decided there was no
future in investing time in baffling discussions that usually ended
with "oh, never mind -- turns out it's a bug" <0.9 wink>.</p>
<p class='source'>Vladimir Marangozov and Tim Peters, 23 Jun
1998</p>
<p class='quotation' id='q78'>Python - why settle for snake oil
when you can have the <em>whole</em> snake?</p>
<p class='source'>Mark Jackson, 26 Jun 1998</p>
<p class='quotation' id='q79'>The problem I have with "SETL sets"
in Python is the same I have with every other language's "killer
core" in Python: SETL is much more than just "a set type", Eiffel
is much more than just fancy pre- and post- conditions, Perl's
approach to regexps is much more than just its isolated regexp
syntax, Scheme is much more than just first-class functions &
lexical closures, and so on. Good languages aren't random
collections of interchangeable features: they have a philosophy and
internal coherence that's never profitably confused with their
surface features.</p>
<p class='source'>Tim Peters, 10 Jul 1998</p>
<p class='quotation' id='q80'>"Since I'm so close to the pickle
module, I just look at the pickles directly, as I'm pretty good at