Config :: Simple, как изменить выходной заголовок по умолчанию? - PullRequest
0 голосов
/ 16 марта 2020

Тестирование генерации на лету конфигурационных файлов в формате ini с пакетом Config :: Simple создает нужный файл, но всегда с тем же заголовком, который включает имя Perl пакет в начале файла. Есть ли у Config::Simple способ изменить печать по умолчанию? Я хотел бы заменить это имя на новое. Возможно ли это с какой-то функцией в пакете?

Вот игрушечный код:

#!/usr/bin/perl

use strict;
use warnings;
use Config::Simple;

my $cfg = new Config::Simple(
        syntax => 'ini'
) or die Config::Simple->error();
$cfg->param("Program.mode", "ALL");
$cfg->param("Program.strategies", "1,2,3,4,5,6,7,8,9,10");
$cfg->param("Data.name_specie", "Homo sapiens");
$cfg->write("test.cfg") or die $cfg->error();

Вывод:

; Config::Simple 4.58
; Mon Mar 16 12:33:55 2020

[Program]
strategies=1,2,3,4,5,6,7,8,9,10
mode=ALL

[Data]
name_specie=Homo sapiens

Просто хотел заменить ; Config::Simple 4.58 line.

Заранее благодарим за ваши предложения.

1 Ответ

4 голосов
/ 16 марта 2020

«Простые» модули часто непросты, потому что они принимают за вас очень много решений. Если вам не нравятся эти решения, вы застряли. Этот конкретный модуль не обновлялся более десяти лет и имеет несколько архитектурных проблем. Если вы хотите файлы INI, используйте другой модуль, такой как Config :: IniFiles , Config :: Tiny или Config :: INI , которые поддерживаются и Flexible.

Моей первой мыслью было создание подкласса и переопределение метода, который добавляет заголовок, так как он был запечен в одном из методов. Это обременительно, потому что модуль использует комбинацию «приватных» подпрограмм и переменных пакета. Я склонен сначала попробовать это, потому что я не мешаю оригинальному пакету:

use strict;
use warnings;
use v5.12;

use Config::Simple;

package Local::Config::Simple {
    use parent qw(Config::Simple);

    # generates a writable string
    sub as_string {
        my $self = shift;

        my $syntax = $self->{_SYNTAX} or die "'_SYNTAX' is not defined";
        my $sub_syntax = $self->{_SUB_SYNTAX} || '';
        my $currtime = localtime;
        my $STRING = undef;
        if ( $syntax eq 'ini' ) {
            while ( my ($block_name, $key_values) = each %{$self->{_DATA}} ) {
                unless ( $sub_syntax eq 'simple-ini' ) {
                    $STRING .= sprintf("[%s]\n", $block_name);
                }
                while ( my ($key, $value) = each %{$key_values} ) {
                    my $values = join (Config::Simple::WRITE_DELIM(), map { Config::Simple::quote_values($_) } @$value);
                    $STRING .= sprintf("%s=%s\n", $key, $values );
                }
                $STRING .= "\n";
            }
        } elsif ( $syntax eq 'http' ) {
            while ( my ($key, $value) = each %{$self->{_DATA}} ) {
                my $values = join (Config::Simple::WRITE_DELIM(), map { Config::Simple::quote_values($_) } @$value);
                $STRING .= sprintf("%s: %s\n", $key, $values);
            }
        } elsif ( $syntax eq 'simple' ) {
            while ( my ($key, $value) = each %{$self->{_DATA}} ) {
                my $values = join (Config::Simple::WRITE_DELIM(), map { Config::Simple::quote_values($_) } @$value);
                $STRING .= sprintf("%s %s\n", $key, $values);
            }
        }
        $STRING .= "\n";
        return $STRING;
    }
}

my $cfg = Local::Config::Simple->new(
        syntax => 'ini'
) or die Config::Simple->error();
$cfg->param("Program.mode", "ALL");
$cfg->param("Program.strategies", "1,2,3,4,5,6,7,8,9,10");
$cfg->param("Data.name_specie", "Homo sapiens");
$cfg->write("file.ini") or die $cfg->error();

, который работает и дает вывод:

[Data]
name_specie=Homo sapiens

[Program]
mode=ALL
strategies=1,2,3,4,5,6,7,8,9,10

Однако, это сломало несколько идей ОО, поэтому Я считаю этот подход неприятным. Я могу сделать немного меньше, исправив исходный пакет, переопределив исходную подпрограмму. Тогда переменные пакета и подпрограммы все еще работают. Сначала загрузите оригинальный модуль, а затем добавьте свои переопределения:

use strict;
use warnings;
use v5.12;

use Config::Simple;
no warnings 'redefine';

package Config::Simple {
    # generates a writable string
    sub as_string {
        my $self = shift;

        my $syntax = $self->{_SYNTAX} or die "'_SYNTAX' is not defined";
        my $sub_syntax = $self->{_SUB_SYNTAX} || '';
        my $currtime = localtime;
        my $STRING = undef;
        if ( $syntax eq 'ini' ) {
            while ( my ($block_name, $key_values) = each %{$self->{_DATA}} ) {
                unless ( $sub_syntax eq 'simple-ini' ) {
                    $STRING .= sprintf("[%s]\n", $block_name);
                }
                while ( my ($key, $value) = each %{$key_values} ) {
                    my $values = join (WRITE_DELIM, map { quote_values($_) } @$value);
                    $STRING .= sprintf("%s=%s\n", $key, $values );
                }
                $STRING .= "\n";
            }
        } elsif ( $syntax eq 'http' ) {
            while ( my ($key, $value) = each %{$self->{_DATA}} ) {
                my $values = join (WRITE_DELIM, map { quote_values($_) } @$value);
                $STRING .= sprintf("%s: %s\n", $key, $values);
            }
        } elsif ( $syntax eq 'simple' ) {
            while ( my ($key, $value) = each %{$self->{_DATA}} ) {
                my $values = join (WRITE_DELIM, map { quote_values($_) } @$value);
                $STRING .= sprintf("%s %s\n", $key, $values);
            }
        }
        $STRING .= "\n";
        return $STRING;
    }
}

my $cfg = Config::Simple->new(
        syntax => 'ini'
) or die Config::Simple->error();
$cfg->param("Program.mode", "ALL");
$cfg->param("Program.strategies", "1,2,3,4,5,6,7,8,9,10");
$cfg->param("Data.name_specie", "Homo sapiens");
$cfg->write("file.ini") or die $cfg->error();

Я довольно много пишу об этом в Эффективное Perl Программирование как способ работы с устаревшим кодом.


В качестве примечания вы спросили, есть ли какой-либо метод в модуле. Вы могли бы просто посмотреть на источник, чтобы увидеть, что происходит и что доступно. Вы бы видели, что заголовок был жестко закодирован в as_string.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...