flnews_post_proc 1.45 → 1.46
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of flnews_post_proc might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +8 -8
- data/bin/flnews_post_proc +2 -1
- data/lib/basic_logging.rb +22 -4
- data/lib/body.rb +6 -2
- data/lib/configuration.rb +3 -1
- data/lib/flnews_post_proc.rb +1 -2
- data/lib/headers.rb +4 -5
- data/lib/new_basic_logging.rb +221 -0
- data/lib/newsgroups.rb +5 -6
- data/lib/version.rb +2 -2
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8f98e3bc6d688a4ee18fd913ee8f04fcc63115dfe50f2ae52f1d7814b5ffb58
|
4
|
+
data.tar.gz: 2193f2432974be939df1ae1d151a5aaa6c37808c76144ad779ccc1371ab0b379
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2f018b1861d3255fcf76a673c4f3b3af6ad7e77d05d245bdf2395bba6d45a1be582c6937c7d12ca766dfc7911c3c0b9a03ebce8e3bd0ada528808d1810c93e7
|
7
|
+
data.tar.gz: d8341b0b9d639d1fdfde99dadda0f786825f5e34c0c39264c691875bc6632435a5e2116a9dc76edcb5e8992718427790de6c0d5a8d07bdcb724caffa2eac9351
|
data/README.md
CHANGED
@@ -93,14 +93,14 @@ some users may not always agree with the result and for arbitrary reasons:
|
|
93
93
|
Custom headers may be defined in the configuration file for the program
|
94
94
|
and will then be added to each outgoing post.
|
95
95
|
|
96
|
-
* The Archive- and X-No-Archive headers are sometimes set to avoid that an
|
97
|
-
article be saved and stays available to search-engines (Google, notably).
|
98
|
-
Test- postings, for example, do probably not justify at all that they would
|
99
|
-
be referenced in search results. The post-processor program can impose the
|
100
|
-
Archive- and X-No-Archive header for all posts to certain newsgroups.
|
101
|
-
|
102
|
-
**ATTN** As of 2024, the X-No-Archive has lost most of its utility
|
103
|
-
is the decision of server operators to honor it or not.
|
96
|
+
* The Archive- and X-No-Archive headers are sometimes set to avoid that an
|
97
|
+
article be saved and stays available to search-engines (Google, notably).
|
98
|
+
Test- postings, for example, do probably not justify at all that they would
|
99
|
+
be referenced in search results. The post-processor program can impose the
|
100
|
+
Archive- and X-No-Archive header for all posts to certain newsgroups.
|
101
|
+
|
102
|
+
**ATTN** As of 2024, the header “X-No-Archive“ has lost most of its utility
|
103
|
+
and it is the decision of server operators to honor it or not.
|
104
104
|
|
105
105
|
* If a news post contains many references to either other posts or Web
|
106
106
|
pages, the text can be cluttered with URLs.
|
data/bin/flnews_post_proc
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/bin/env ruby
|
2
2
|
#encoding: UTF-8
|
3
|
+
|
3
4
|
=begin
|
4
5
|
/***************************************************************************
|
5
6
|
* ©2023-2024, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
@@ -32,7 +33,7 @@ self.extend(BasicLogging)
|
|
32
33
|
|
33
34
|
msg = PROGNAME.dup << ' ' << PROGVERSION << ' starting'
|
34
35
|
msg = "–––––– " << msg << " ––––––"
|
35
|
-
|
36
|
+
clear_log
|
36
37
|
info msg
|
37
38
|
# Get a configuration
|
38
39
|
config = Configuration::instance
|
data/lib/basic_logging.rb
CHANGED
@@ -48,15 +48,19 @@ module BasicLogging
|
|
48
48
|
|
49
49
|
# set the log level
|
50
50
|
def set_level(lv)
|
51
|
-
if lv.respond_to?(:to_str)
|
51
|
+
if lv.respond_to?(:to_str) && Levels.keys.include?(lv.strip.to_sym)
|
52
52
|
lv = Levels[lv.to_sym]
|
53
|
+
elsif lv.respond_to?(:to_sym) && Levels.keys.include?(lv)
|
54
|
+
lv = Levels[lv]
|
53
55
|
end
|
54
56
|
|
55
57
|
if(!lv || (lv.respond_to?(:to_int) && lv >= DEBUG && lv <= FATAL) )
|
56
58
|
@@log_level = lv
|
57
59
|
else
|
58
|
-
|
59
|
-
|
60
|
+
msg = __FILE__.dup << ": ERROR : invalid log level \"" << lv.to_s << "\""
|
61
|
+
msg << "\n" << "Keepinng old log level " << Levels.keys.detect {| k| Levels[k] == @@log_level}.to_s
|
62
|
+
STDERR.puts msg
|
63
|
+
puts msg
|
60
64
|
end
|
61
65
|
end
|
62
66
|
|
@@ -91,13 +95,27 @@ module BasicLogging
|
|
91
95
|
end
|
92
96
|
end
|
93
97
|
|
98
|
+
def target
|
99
|
+
@@target.path if @@target
|
100
|
+
end
|
101
|
+
|
102
|
+
def level
|
103
|
+
@@level.to_s if @@level
|
104
|
+
end
|
105
|
+
|
106
|
+
# Clear the log (-file)
|
107
|
+
def clear_log
|
108
|
+
if @@target && @@target.respond_to?(:truncate)
|
109
|
+
@@target.truncate(0)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
94
113
|
alias :debug :log
|
95
114
|
alias :info :log
|
96
115
|
alias :warn :log
|
97
116
|
alias :error :log
|
98
117
|
alias :fatal :log
|
99
118
|
|
100
|
-
attr_reader :target, :log_level
|
101
119
|
|
102
120
|
private
|
103
121
|
|
data/lib/body.rb
CHANGED
@@ -87,7 +87,7 @@ class Body
|
|
87
87
|
i = i.next
|
88
88
|
line = @lines[i]
|
89
89
|
end
|
90
|
-
# check if there is a
|
90
|
+
# check if there is a quote, at all
|
91
91
|
if(line.start_with?('>'))
|
92
92
|
debug("\tfound intro " << ointro)
|
93
93
|
# variables are part of the $intro.
|
@@ -121,7 +121,11 @@ class Body
|
|
121
121
|
def join
|
122
122
|
return @lines.join("\r\n")
|
123
123
|
end
|
124
|
-
|
124
|
+
# ------->
|
125
|
+
# TODO : Concentrate all URL/URI munging functionality in 1 or 2 helper
|
126
|
+
# classes, e.g. Body::News and Body::Http
|
127
|
+
# <------
|
128
|
+
|
125
129
|
# Verify and possibly correct links in the post.
|
126
130
|
# Simple.
|
127
131
|
def handle_urls()
|
data/lib/configuration.rb
CHANGED
@@ -25,7 +25,6 @@ class Configuration
|
|
25
25
|
include Singleton
|
26
26
|
include BasicLogging
|
27
27
|
|
28
|
-
self.extend(BasicLogging)
|
29
28
|
|
30
29
|
def initialize()
|
31
30
|
debug 'Configuration::initialize()'
|
@@ -114,7 +113,10 @@ class Configuration
|
|
114
113
|
def read_config
|
115
114
|
if File::exist?(@config_file) && File::readable?(@config_file)
|
116
115
|
begin
|
116
|
+
puts "config_file is " << @config_file
|
117
117
|
@conf = YAML::load_file(@config_file)
|
118
|
+
puts 'load_file'
|
119
|
+
|
118
120
|
@conf.transform_keys!{|k| k.to_sym}
|
119
121
|
@keys = @conf.keys
|
120
122
|
clevel = @conf[:LOG_LEVEL]
|
data/lib/flnews_post_proc.rb
CHANGED
@@ -29,11 +29,10 @@ $LN = "\r\n"
|
|
29
29
|
# The main application class.
|
30
30
|
# Does it.
|
31
31
|
class PostProcessor
|
32
|
-
# class-level configuration object
|
33
|
-
@@config = Configuration.instance
|
34
32
|
include BasicLogging
|
35
33
|
|
36
34
|
def initialize(article_text)
|
35
|
+
@config = Configuration.instance
|
37
36
|
# for simplicity.
|
38
37
|
# separate the headers and the body.
|
39
38
|
debug ' initializing headers'
|
data/lib/headers.rb
CHANGED
@@ -20,13 +20,12 @@ require_relative 'newsgroups'
|
|
20
20
|
# an object of this class represents the headers of a news-article
|
21
21
|
|
22
22
|
class Headers
|
23
|
-
# class-level configuration object
|
24
|
-
@@config = Configuration.instance
|
25
23
|
include BasicLogging
|
26
24
|
|
27
25
|
# read the headers from the article
|
28
26
|
def initialize(article_text)
|
29
27
|
|
28
|
+
@config = Configuration.instance
|
30
29
|
line = nil
|
31
30
|
# transform the article to an array.
|
32
31
|
debug('before split, article_text is : ' << article_text)
|
@@ -105,10 +104,10 @@ class Headers
|
|
105
104
|
@headers["X-No-Archive".to_sym] = no_archive
|
106
105
|
@headers["Archive".to_sym] = 'no'
|
107
106
|
end
|
108
|
-
if
|
109
|
-
ch =
|
107
|
+
if @config.CUSTOM_HEADERS
|
108
|
+
ch = @config.CUSTOM_HEADERS
|
110
109
|
debug('setting custom headers : ' << ch.inspect)
|
111
|
-
|
110
|
+
@config.CUSTOM_HEADERS.each do |pair|
|
112
111
|
ch = pair.split(':')
|
113
112
|
hn = ch[0].strip
|
114
113
|
hv = ch[1].strip
|
@@ -0,0 +1,221 @@
|
|
1
|
+
#!/bin/env ruby
|
2
|
+
#encoding: UTF-8
|
3
|
+
=begin
|
4
|
+
/***************************************************************************
|
5
|
+
* 2023-2024, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
6
|
+
* This program is free software; you can redistribute it and/or modify *
|
7
|
+
* it under the terms of the WTFPL 2.0 or later, see *
|
8
|
+
* http://www.wtfpl.net/about/ *
|
9
|
+
* *
|
10
|
+
* This program is distributed in the hope that it will be useful, *
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
13
|
+
* *
|
14
|
+
***************************************************************************/
|
15
|
+
=end
|
16
|
+
|
17
|
+
require 'io/wait'
|
18
|
+
#
|
19
|
+
# Simplified logging.
|
20
|
+
# See example code at the bottom of this file.
|
21
|
+
# Execute this file to see the output.
|
22
|
+
module BasicLogging
|
23
|
+
|
24
|
+
DEBUG = 0
|
25
|
+
INFO = 1
|
26
|
+
WARN = 2
|
27
|
+
ERROR = 3
|
28
|
+
FATAL = 4
|
29
|
+
UNKNOWN = nil
|
30
|
+
|
31
|
+
# this is mainly for the translation of method calls into log levels
|
32
|
+
Levels = {:debug => DEBUG, :info => INFO, :warn => WARN, :error => ERROR,
|
33
|
+
:fatal => FATAL, :unknown => UNKNOWN}
|
34
|
+
|
35
|
+
@@log_level = UNKNOWN
|
36
|
+
@@log_target = STDOUT
|
37
|
+
@@muted = []
|
38
|
+
|
39
|
+
# do not log, if caller is obj (class or instance)
|
40
|
+
def self.mute(obj)
|
41
|
+
name = obj.class == Class ? obj.name.dup : obj.class.name
|
42
|
+
@@muted << name
|
43
|
+
end
|
44
|
+
|
45
|
+
# Log, if caller is obj (class or instance)
|
46
|
+
def self.unmute(obj)
|
47
|
+
name = obj.class == Class ? obj.name.dup : obj.class.name
|
48
|
+
if @@muted.include?(name)
|
49
|
+
@@muted.delete(name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.is_muted?(obj)
|
54
|
+
name = obj.class == Class ? obj.name.dup : obj.class.name
|
55
|
+
@@muted.include?(name)
|
56
|
+
end
|
57
|
+
|
58
|
+
# set the log level
|
59
|
+
def set_level(lv)
|
60
|
+
# String – like 'debug' – or symbol – like :debug?
|
61
|
+
if lv
|
62
|
+
if lv.respond_to?(:to_str)
|
63
|
+
lv = lv.downcase.to_sym
|
64
|
+
# integer or nil
|
65
|
+
lv = Levels[lv]
|
66
|
+
elsif lv.respond_to?(:to_sym) && Levels.keys.include?(lv)
|
67
|
+
# integer or nil
|
68
|
+
lv = Levels[lv]
|
69
|
+
else
|
70
|
+
lv = nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
# set level to Integer or nil
|
74
|
+
if(!lv || (lv.respond_to?(:to_int) && lv >= DEBUG && lv <= FATAL) )
|
75
|
+
@@log_level = lv
|
76
|
+
else
|
77
|
+
STDERR.puts __FILE__.dup << ": ERROR : invalid log level \"" << lv.to_s << "\""
|
78
|
+
STDERR.puts "Keepinng old log level " << Levels.keys.detect {| k| Levels[k] == @@log_level}.to_s
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# set the log target
|
83
|
+
def set_target(tg)
|
84
|
+
if !tg || tg.respond_to?(:to_str) && tg.strip.empty?
|
85
|
+
@@log_target = nil
|
86
|
+
elsif tg.respond_to?(:to_io) && tg.wait_writable
|
87
|
+
@@log_target = tg
|
88
|
+
elsif(!File::exist?(tg) || ( File.file?(tg) && File.writable?(tg) ) )
|
89
|
+
@@log_target = File.open(tg, 'w+')
|
90
|
+
else
|
91
|
+
STDERR.puts __FILE__.dup << ': ERROR : target ' << tg << ' cannot be set'
|
92
|
+
STDERR.puts "Keeping old target " << @@log_target.inspect
|
93
|
+
return
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Output of log messages, depending on the log level set for the calling class
|
98
|
+
# and the name of the alias method which is actually called.
|
99
|
+
def log(message)
|
100
|
+
if !BasicLogging.is_muted?(self)
|
101
|
+
# how has this method been called?
|
102
|
+
mlevel = __callee__
|
103
|
+
if Levels.has_key?(mlevel) && Levels[mlevel] <= FATAL
|
104
|
+
# output only for levels equal or above the value that corresponds to
|
105
|
+
# the calling alias.
|
106
|
+
if @@log_level && Levels[mlevel] >= @@log_level
|
107
|
+
format_log( message, mlevel)
|
108
|
+
end
|
109
|
+
else
|
110
|
+
STDERR.puts __FILE__.dup << ": ERROR : invalid log level \"" << mlevel.to_s << "\""
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def target
|
116
|
+
@@log_target.path if @@log_target
|
117
|
+
end
|
118
|
+
|
119
|
+
def level
|
120
|
+
@@log_level.to_s if @@log_level
|
121
|
+
end
|
122
|
+
|
123
|
+
# Clear the log (-file)
|
124
|
+
def clear_log
|
125
|
+
if @@log_target && @@log_target.respond_to?(:truncate)
|
126
|
+
File::truncate(@@log_target, 0)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
alias :debug :log
|
131
|
+
alias :info :log
|
132
|
+
alias :warn :log
|
133
|
+
alias :error :log
|
134
|
+
alias :fatal :log
|
135
|
+
|
136
|
+
|
137
|
+
private
|
138
|
+
|
139
|
+
# 1 format_log for all loggers.
|
140
|
+
def format_log(message, mlevel)
|
141
|
+
if @@log_target
|
142
|
+
# indicate if a registered class or the registered object of a class is calling.
|
143
|
+
name = self.class == Class ? self.name.dup << ' [class]' : self.class.name
|
144
|
+
str = '' << name << ' ' << mlevel.to_s << ' ' << Time.now.strftime("%H:%M:%S:%6N") << ': ' << message.gsub("\n", "\n |")
|
145
|
+
@@log_target.puts str
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
#---------test: execute file----------
|
150
|
+
if $0 == __FILE__
|
151
|
+
Array.extend(BasicLogging)
|
152
|
+
Array.set_level("info")
|
153
|
+
Array.info('TEST')
|
154
|
+
ar = Array.new
|
155
|
+
ar.extend(BasicLogging)
|
156
|
+
# --- no output :
|
157
|
+
l = __LINE__
|
158
|
+
ar.debug(l.next.to_s << ': debug-test 0')
|
159
|
+
# output
|
160
|
+
ar.set_level(:debug)
|
161
|
+
l = __LINE__
|
162
|
+
ar.debug(l.next.to_s << ': debug-test 1')
|
163
|
+
|
164
|
+
obj = Object.new
|
165
|
+
obj.extend(BasicLogging)
|
166
|
+
obj.set_level(BasicLogging::DEBUG)
|
167
|
+
puts "--------debug-----------"
|
168
|
+
obj.debug('debug')
|
169
|
+
obj.info('info')
|
170
|
+
obj.warn('warn')
|
171
|
+
obj.error('error')
|
172
|
+
obj.fatal('fatal')
|
173
|
+
puts "--------info-----------"
|
174
|
+
obj.set_level("info")
|
175
|
+
obj.debug('debug')
|
176
|
+
obj.info('info')
|
177
|
+
obj.warn('warn')
|
178
|
+
obj.error('error')
|
179
|
+
obj.fatal('fatal')
|
180
|
+
puts "--------fatal-----------"
|
181
|
+
obj.set_level("fatal")
|
182
|
+
obj.debug('debug')
|
183
|
+
obj.info('info')
|
184
|
+
obj.warn('warn')
|
185
|
+
obj.error('error')
|
186
|
+
obj.fatal('fatal')
|
187
|
+
puts "--------UNKNOWN-----------"
|
188
|
+
obj.set_level(nil)
|
189
|
+
obj.debug('debug')
|
190
|
+
obj.info('info')
|
191
|
+
obj.warn('warn')
|
192
|
+
obj.error('error')
|
193
|
+
obj.fatal('fatal')
|
194
|
+
puts " ------ Output into file ----"
|
195
|
+
obj.set_target "/tmp/test_log.log"
|
196
|
+
puts " ------ INFO -----------"
|
197
|
+
obj.set_level BasicLogging::INFO
|
198
|
+
obj.info('info output')
|
199
|
+
|
200
|
+
obj.info('info output 2')
|
201
|
+
puts "---------- invalid -------"
|
202
|
+
obj.set_target(STDOUT)
|
203
|
+
obj.set_level "power"
|
204
|
+
begin
|
205
|
+
File.open("/tmp/invalid_log", 'r') do |f|
|
206
|
+
obj.set_target f
|
207
|
+
end
|
208
|
+
rescue Exception => er
|
209
|
+
obj.error "ERROR! " << er.message
|
210
|
+
end
|
211
|
+
puts "------------ muted -------"
|
212
|
+
BasicLogging::mute obj
|
213
|
+
puts "is muted? " << BasicLogging.is_muted?(obj).to_s
|
214
|
+
obj.info "test"
|
215
|
+
puts "--------- unmute ----"
|
216
|
+
BasicLogging::unmute obj
|
217
|
+
puts "is muted? " << BasicLogging.is_muted?(obj).to_s
|
218
|
+
obj.info "back again"
|
219
|
+
end
|
220
|
+
|
221
|
+
# EOF
|
data/lib/newsgroups.rb
CHANGED
@@ -20,11 +20,10 @@ require_relative 'configuration'
|
|
20
20
|
require_relative 'basic_logging'
|
21
21
|
|
22
22
|
class Newsgroups
|
23
|
-
# class-level configuration object
|
24
|
-
@@config = Configuration.instance
|
25
|
-
include BasicLogging
|
26
23
|
|
24
|
+
include BasicLogging
|
27
25
|
def initialize(groups)
|
26
|
+
@config = Configuration.instance
|
28
27
|
@groups = groups.split(',')
|
29
28
|
debug('set signature, intro, no_archive')
|
30
29
|
# set details for this post
|
@@ -50,7 +49,7 @@ class Newsgroups
|
|
50
49
|
# only one group.
|
51
50
|
group = @groups[0]
|
52
51
|
# all configured intro-lines.
|
53
|
-
gintros =
|
52
|
+
gintros = @config.GROUP_INTROS
|
54
53
|
|
55
54
|
if gintros && gintros.respond_to?(:to_hash)
|
56
55
|
# find the intro for the group.
|
@@ -93,7 +92,7 @@ class Newsgroups
|
|
93
92
|
@signature = nil
|
94
93
|
# 1 group
|
95
94
|
group = @groups[0]
|
96
|
-
gsigs =
|
95
|
+
gsigs = @config.GROUP_SIGS
|
97
96
|
|
98
97
|
if gsigs && gsigs.respond_to?(:to_hash)
|
99
98
|
# find the signature for the group
|
@@ -124,7 +123,7 @@ class Newsgroups
|
|
124
123
|
# define the no_archive header.
|
125
124
|
def set_no_archive
|
126
125
|
@no_archive = nil
|
127
|
-
xgs =
|
126
|
+
xgs = @config.NO_ARCHIVE_GROUPS
|
128
127
|
if xgs && !xgs.empty? && xgs.detect {|g| @groups[0].match(g) }
|
129
128
|
debug("setting no_archive")
|
130
129
|
@no_archive = 'yes'
|
data/lib/version.rb
CHANGED
@@ -14,8 +14,8 @@
|
|
14
14
|
=end
|
15
15
|
|
16
16
|
PROGNAME = 'flnews_post_proc'
|
17
|
-
PROGVERSION = "1.
|
17
|
+
PROGVERSION = "1.46"
|
18
18
|
AUTHORS = "Michael Uplawski"
|
19
19
|
EMAIL = "michael.uplawski@uplawski.eu"
|
20
20
|
YEARS = "2023 - 2024"
|
21
|
-
SUMMARY = "
|
21
|
+
SUMMARY = "Logging modul: unused functionality corrected."
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flnews_post_proc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '1.
|
4
|
+
version: '1.46'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Uplawski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-05-
|
11
|
+
date: 2024-05-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: diffy
|
@@ -56,6 +56,7 @@ files:
|
|
56
56
|
- lib/flnews_post_proc.conf
|
57
57
|
- lib/flnews_post_proc.rb
|
58
58
|
- lib/headers.rb
|
59
|
+
- lib/new_basic_logging.rb
|
59
60
|
- lib/newsgroups.rb
|
60
61
|
- lib/override.rb
|
61
62
|
- lib/ruby_dlg
|
@@ -82,8 +83,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
83
|
- !ruby/object:Gem::Version
|
83
84
|
version: '0'
|
84
85
|
requirements: []
|
85
|
-
rubygems_version: 3.
|
86
|
+
rubygems_version: 3.5.3
|
86
87
|
signing_key:
|
87
88
|
specification_version: 4
|
88
|
-
summary: '
|
89
|
+
summary: 'Logging modul: unused functionality corrected.'
|
89
90
|
test_files: []
|