module MyPrecious::Reporting

Common behavior in dependency report generation

The methods here are not specific to any language or dependency management framework. They do work with ColumnOrder and an expected set of attributes on the dependency information objects.

Public Class Methods

common_col_title(attr) click to toggle source

Converts an attribute name to the column title for generic attributes

Dependency info classes (like RubyGemInfo) can delegate common column title generation to this function.

# File lib/myprecious.rb, line 279
def common_col_title(attr)
  case attr
  when :current_version then 'Our Version'
  when :age then 'Age (days)'
  when :latest_version then 'Latest Version'
  when :latest_released then 'Date Available'
  when :recommended_version then 'Recommended Version'
  when :license then 'License Type'
  when :changelog then 'Change Log'
  when :obsolescence then 'How Bad'
  when :cves then 'CVEs'
  else
    warn("'#{attr}' column does not have a mapped name")
    attr
  end
end
default_output_fpath(dir) click to toggle source

Compute the default output filepath for a directory

# File lib/myprecious.rb, line 220
def default_output_fpath(dir)
  dir / (GitInfoExtractor.new(dir).repo_name + "-dependency-tracking.md")
end
header_lines(order, titlizer) click to toggle source

Generate header lines for the output Markdown table

Returns an Array of strings, currently two lines giving header text and divider row.

# File lib/myprecious.rb, line 255
def header_lines(order, titlizer)
  col_titles = order.map {|c| titlizer.call(c)}
  
  # Check that all attributes in #order round-trip through the title name
  order.zip(col_titles) do |attr, title|
    unless title.kind_of?(Symbol) || ColumnOrder.col_from_text_name(title) == attr
      raise "'#{attr}' does not round-trip (rendered as #{result.inspect})"
    end
  end
  
  return [
    col_titles.join(" | "),
    (["---"] * col_titles.length).join(" | "),
  ]
end
obsolescence_by_age(days, at_least_moderate: false) click to toggle source

Determine obsolescence level from days

Returns one of nil, :mild, :moderate, or :severe.

at_least_moderate: allows putting a floor of :moderate obsolescence on the result.

# File lib/myprecious.rb, line 305
def obsolescence_by_age(days, at_least_moderate: false)
  return case 
  when days < 270
    at_least_moderate ? :moderate : nil
  when days < 500
    at_least_moderate ? :moderate : :mild
  when days < 730
    :moderate
  else
    :severe
  end
end
on_dependency(name) { || ... } click to toggle source

Wrap output from processing of an individual dependency with intro and outro messages

# File lib/myprecious.rb, line 323
def on_dependency(name)
  progress_out = $stdout
  progress_out.puts("--- Reporting on #{name}...")
  yield
  progress_out.puts("    (done)")
end
read_column_order_from(fpath) click to toggle source

Read the column order from the file at the given path

If fpath indicates a file that does not exist, return the default ColumnOrder.

# File lib/myprecious.rb, line 231
def read_column_order_from(fpath)
  result = ColumnOrder.new
  begin
    prev_line = nil
    fpath.open {|inf| inf.each_line do |line|
      if prev_line && /^-+(?:\|-+)*$/ =~ line.gsub(' ', '')
        result.read_order_from_headers(prev_line)
        break
      end
      prev_line = line
    end}
  rescue Errno::ENOENT
    # No problem
  end
  return result
end

Private Instance Methods

common_col_title(attr) click to toggle source

Converts an attribute name to the column title for generic attributes

Dependency info classes (like RubyGemInfo) can delegate common column title generation to this function.

# File lib/myprecious.rb, line 279
def common_col_title(attr)
  case attr
  when :current_version then 'Our Version'
  when :age then 'Age (days)'
  when :latest_version then 'Latest Version'
  when :latest_released then 'Date Available'
  when :recommended_version then 'Recommended Version'
  when :license then 'License Type'
  when :changelog then 'Change Log'
  when :obsolescence then 'How Bad'
  when :cves then 'CVEs'
  else
    warn("'#{attr}' column does not have a mapped name")
    attr
  end
end
default_output_fpath(dir) click to toggle source

Compute the default output filepath for a directory

# File lib/myprecious.rb, line 220
def default_output_fpath(dir)
  dir / (GitInfoExtractor.new(dir).repo_name + "-dependency-tracking.md")
end
header_lines(order, titlizer) click to toggle source

Generate header lines for the output Markdown table

Returns an Array of strings, currently two lines giving header text and divider row.

# File lib/myprecious.rb, line 255
def header_lines(order, titlizer)
  col_titles = order.map {|c| titlizer.call(c)}
  
  # Check that all attributes in #order round-trip through the title name
  order.zip(col_titles) do |attr, title|
    unless title.kind_of?(Symbol) || ColumnOrder.col_from_text_name(title) == attr
      raise "'#{attr}' does not round-trip (rendered as #{result.inspect})"
    end
  end
  
  return [
    col_titles.join(" | "),
    (["---"] * col_titles.length).join(" | "),
  ]
end
obsolescence_by_age(days, at_least_moderate: false) click to toggle source

Determine obsolescence level from days

Returns one of nil, :mild, :moderate, or :severe.

at_least_moderate: allows putting a floor of :moderate obsolescence on the result.

# File lib/myprecious.rb, line 305
def obsolescence_by_age(days, at_least_moderate: false)
  return case 
  when days < 270
    at_least_moderate ? :moderate : nil
  when days < 500
    at_least_moderate ? :moderate : :mild
  when days < 730
    :moderate
  else
    :severe
  end
end
on_dependency(name) { || ... } click to toggle source

Wrap output from processing of an individual dependency with intro and outro messages

# File lib/myprecious.rb, line 323
def on_dependency(name)
  progress_out = $stdout
  progress_out.puts("--- Reporting on #{name}...")
  yield
  progress_out.puts("    (done)")
end
read_column_order_from(fpath) click to toggle source

Read the column order from the file at the given path

If fpath indicates a file that does not exist, return the default ColumnOrder.

# File lib/myprecious.rb, line 231
def read_column_order_from(fpath)
  result = ColumnOrder.new
  begin
    prev_line = nil
    fpath.open {|inf| inf.each_line do |line|
      if prev_line && /^-+(?:\|-+)*$/ =~ line.gsub(' ', '')
        result.read_order_from_headers(prev_line)
        break
      end
      prev_line = line
    end}
  rescue Errno::ENOENT
    # No problem
  end
  return result
end