how_is 18.0.2 → 18.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7af6f8d15c041385b198ac7aab7e3d0f7daec229
4
- data.tar.gz: 8633dfde4863be308641d36c4aad7983981c1b03
3
+ metadata.gz: d6f35707314d01b26c01a857209228e882ab19e8
4
+ data.tar.gz: 488bb2052b79301f7c3919f84504e7a786410506
5
5
  SHA512:
6
- metadata.gz: 0b9ed47bce960ecac6e3b32b1cf95495e6a14624f7a1c713709b8e5a92a91a4c4bb30d1ebe544ae8d06dc6f2099fe72d45588f734c5395187fc7cdddf6e31e34
7
- data.tar.gz: d03d18caf52eb5b3195c925ce87137399ed7f172aed06c653afefc6b695f4079ca1635d5ac5bf05ded466f1f4f6afedc0705ab8810732a53b821a6eb71157e1b
6
+ metadata.gz: 73c0fd55cfae0d7a25dfb60e431bb99a5826872af8d03db6fdef9b44bdda900746210b32bc220026b03c0fe36bc95c7a0bdf0819cdb9ce9868932af915608bed
7
+ data.tar.gz: 6fc00770653ba6af093c986d4135aa5b30fd187f8a6c89e260fc4b33ec18eee57ffb8323d90a2e2b1f8c2ecc3f08845cff37e8c642a07ed5ab9df3c65ae6e0d3
data/.hound.yml ADDED
@@ -0,0 +1,2 @@
1
+ ruby:
2
+ config_file: .rubocop.yml
data/.rubocop.yml ADDED
@@ -0,0 +1,126 @@
1
+ # Exceptions should inherit from StandardError.
2
+ # (RuboCop default is to inherit from RuntimeError.)
3
+ Lint/InheritException:
4
+ EnforcedStyle: standard_error
5
+
6
+ # The guiding principle of classes is SRP, SRP can't be accurately measured by LoC
7
+ #Metrics/ClassLength:
8
+ # Max: 1500
9
+
10
+ # Still try for 80, but we'll allow 110 because there's a not-insignificant
11
+ # number of cases where we have long lines.
12
+ #
13
+ # It may be worth revisiting this in the future and refactoring those lines.
14
+ Metrics/LineLength:
15
+ Max: 120
16
+
17
+ # Too short methods lead to extraction of single-use methods, which can make
18
+ # the code easier to read (by naming things), but can also clutter the class
19
+ Metrics/MethodLength:
20
+ Max: 20
21
+
22
+ # Most readable form.
23
+ Style/AlignHash:
24
+ EnforcedHashRocketStyle: table
25
+ EnforcedColonStyle: table
26
+
27
+ # This codebase may be English, but some English words contain diacritics.
28
+ Style/AsciiComments:
29
+ Enabled: false
30
+
31
+ # Despite the fact that some English words contain diacritics, we want all
32
+ # method names to be writable by people who don't have an easy way to type
33
+ # words with diacritics.
34
+ Style/AsciiIdentifiers:
35
+ Enabled: true
36
+
37
+ # { ... } for multi-line blocks is okay, follow Weirichs rule instead:
38
+ # https://web.archive.org/web/20140221124509/http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc
39
+ Style/BlockDelimiters:
40
+ Enabled: false
41
+
42
+ # Unicode is good, mkay?
43
+ Style/Encoding:
44
+ Enabled: true
45
+
46
+ # Force Unix line endings.
47
+ Style/EndOfLine:
48
+ Enabled: true
49
+ EnforcedStyle: lf
50
+
51
+ # A lot of the approaches I use for making things readable makes this angry.
52
+ # E.g., formatting multiple consecutive assignments so that the equal signs
53
+ # and values line up.
54
+ #
55
+ # foobar = 'blah'
56
+ # baz = 'asdf'
57
+ # beep = 'boop'
58
+ Style/ExtraSpacing:
59
+ Enabled: false
60
+
61
+ # Freeze string literals to future-proof the code.
62
+ # TODO: Enable this always. (Disabled due to not knowing what will happen.)
63
+ Style/FrozenStringLiteralComment:
64
+ Enabled: true
65
+ #EnforcedStyle: always
66
+
67
+ # Mixing hash styles just looks silly.
68
+ # http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/HashSyntax
69
+ Style/HashSyntax:
70
+ EnforcedStyle: no_mixed_keys
71
+
72
+ # I deplore assignments in conditions and never want them in any codebase
73
+ # I have direct control over.
74
+ Style/ParenthesesAroundCondition:
75
+ AllowSafeAssignment: false
76
+ Lint/AssignmentInCondition:
77
+ AllowSafeAssignment: false
78
+
79
+ # Use [] for `%`-literal delimiters (e.g. for %q[]) that RuboCop doesn't define
80
+ # anything for. (E.g., %q[].)
81
+ #
82
+ # The reason I prefer [] instead of () is that most of the time I use
83
+ # `%`-literals is inside of function calls, and using () makes it blend in too
84
+ # much.
85
+ Style/PercentLiteralDelimiters:
86
+ Enabled: true
87
+ PreferredDelimiters:
88
+ default: "[]"
89
+
90
+ # `has_key?` and `has_value?` are clearer than `key?` and `value?`.
91
+ Style/PreferredHashMethods:
92
+ Enabled: true
93
+ EnforcedStyle: verbose
94
+
95
+ # do / end blocks should be used for side effects,
96
+ # methods that run a block for side effects and have
97
+ # a useful return value are rare, assign the return
98
+ # value to a local variable for those cases.
99
+ Style/MethodCalledOnDoEndBlock:
100
+ Enabled: true
101
+
102
+ # Indenting the chained dots beneath each other is not supported by this cop,
103
+ # see https://github.com/bbatsov/rubocop/issues/1633
104
+ Style/MultilineOperationIndentation:
105
+ Enabled: false
106
+
107
+ # {'foo' => 'bar'} not { 'foo' => 'bar' }
108
+ Style/SpaceInsideHashLiteralBraces:
109
+ Enabled: true
110
+ EnforcedStyle: no_space
111
+
112
+ # Use double quotes everywhere by default.
113
+ # TODO: Enable Style/StringLiterals cop. Disabled due to number of violations.
114
+ Style/StringLiterals:
115
+ Enabled: false
116
+ #EnforcedStyle: double_quotes
117
+
118
+ # Require parentheses around complex ternary conditions.
119
+ Style/TernaryParentheses:
120
+ Enabled: true
121
+ EnforcedStyle: require_parentheses_when_complex
122
+
123
+ # Require a comma after the last item in an array or hash if each item is on
124
+ # its own line.
125
+ Style/TrailingCommaInLiteral:
126
+ EnforcedStyleForMultiline: comma
data/CHANGELOG.md CHANGED
@@ -9,6 +9,25 @@ this project adheres to [Semantic Versioning](http://semver.org).
9
9
 
10
10
  (Nothing so far.)
11
11
 
12
+ ## [v18.0.3]
13
+
14
+ This release ([snapshot](https://github.com/how-is/how_is/tree/v18.0.3))
15
+ fixes the things the last few releases broke. I think. Hopefully.
16
+
17
+ It also includes some refactoring work, and the addition of a RuboCop
18
+ configuration.
19
+
20
+ @duckinator enabled [Hound CI](https://houndci.com) for the repository, which
21
+ should find any RuboCop violations that are added in PRs. The preexisting
22
+ RuboCop violations (of which there are many) need to be addressed separately,
23
+ and there will likely be an entire release dedicated to that.
24
+
25
+ ### Changes
26
+
27
+ * Add RuboCop config ([#158](https://github.com/how-is/how_is/pull/158))
28
+ * CLI parser refactor ([#157](https://github.com/how-is/how_is/pull/157))
29
+ * exe/how_is: Reinstate to_json, to_html ([#150](https://github.com/how-is/how_is/pull/150), by @olleolleolle)
30
+
12
31
  ## [v18.0.2]
13
32
 
14
33
  This release ([snapshot](https://github.com/how-is/how_is/tree/v18.0.2))
data/Gemfile CHANGED
@@ -3,3 +3,10 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in how_is.gemspec
4
4
  gemspec
5
5
 
6
+ # Everything says to put it here. It feels like it should go in the gemspec?
7
+ # SOMEBODY WHO KNOWS WHAT THEY'RE DOING PLEASE LET ME KNOW WHAT TO DO HERE.
8
+ group :test, :development do
9
+ # Matches version used by Hound, even though there's newer releases.
10
+ # https://github.com/houndci/linters/blob/master/Gemfile.lock
11
+ gem 'rubocop', '~> 0.46.0', require: false
12
+ end
data/exe/how_is CHANGED
@@ -4,8 +4,7 @@ require "how_is"
4
4
  require "how_is/cli"
5
5
 
6
6
  begin
7
- parser = HowIs::CLI::Parser.new
8
- result = parser.call(ARGV)
7
+ result = HowIs::CLI.parse(ARGV)
9
8
  rescue HowIs::CLI::OptionsError => e
10
9
  if ENV['SHOW_TRACE']
11
10
  raise
@@ -14,9 +13,7 @@ rescue HowIs::CLI::OptionsError => e
14
13
  end
15
14
  end
16
15
 
17
- opts = result[:opts]
18
- options = result[:options]
19
- arguments = result[:arguments]
16
+ options = result[:options]
20
17
 
21
18
  if options[:help]
22
19
  puts result[:opts]
@@ -26,21 +23,11 @@ elsif options[:version]
26
23
  exit
27
24
  end
28
25
 
29
- def save_files(reports)
30
- reports.each do |file, report|
31
- format = file.split('.').last
32
-
33
- File.open(file, 'w') do |f|
34
- f.write report
35
- end
36
- end
37
- end
38
-
39
26
  begin
40
27
  if options[:config]
41
28
  reports = HowIs.from_config(YAML.load_file(options[:config]))
42
29
 
43
- save_files(reports)
30
+ reports.each { |file, report| HowIs::Report.save_report(file, report) }
44
31
  else
45
32
  report =
46
33
  if options[:from]
@@ -50,7 +37,10 @@ begin
50
37
  HowIs.new(options[:repository])
51
38
  end
52
39
 
53
- save_files({ options[:report] => report })
40
+ HowIs::Report.save_report(
41
+ options[:report],
42
+ HowIs::Report.to_format_based_on(options[:report], report)
43
+ )
54
44
  end
55
45
 
56
46
  rescue => e
data/how_is.gemspec CHANGED
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+
2
3
  lib = File.expand_path('../lib', __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'how_is/version'
data/lib/how_is/cli.rb CHANGED
@@ -22,17 +22,14 @@ class HowIs::CLI
22
22
  class NoRepositoryError < OptionsError
23
23
  end
24
24
 
25
- class Parser
26
- attr_reader :opts
27
-
28
- # Parses +argv+ to generate an options Hash to control the behavior of
29
- # the library.
30
- def call(argv)
31
- opts = Slop::Options.new
32
-
33
- # General usage information.
34
- opts.banner =
35
- <<-EOF.gsub(/ *\| ?/, '')
25
+ # Parses +argv+ to generate an options Hash to control the behavior of
26
+ # the library.
27
+ def self.parse(argv)
28
+ opts = Slop::Options.new
29
+
30
+ # General usage information.
31
+ opts.banner =
32
+ <<-EOF.gsub(/ *\| ?/, '')
36
33
  | Usage: how_is REPOSITORY [--report REPORT_FILE] [--from JSON_FILE]
37
34
  | how_is --config CONFIG_FILE
38
35
  |
@@ -42,74 +39,73 @@ class HowIs::CLI
42
39
  | E.g., if you wanted to check https://github.com/how-is/how_is,
43
40
  | you'd run `how_is how-is/how_is`.
44
41
  |
45
- EOF
46
-
47
- opts.separator ""
48
- opts.separator "Options:"
49
-
50
- # Allowed arguments:
51
- opts.bool "-h", "--help", "Print help text"
52
- opts.string "--config", "YAML config file, used to generate a group of reports"
53
- opts.string "--from", "JSON report file, used instead of fetching the data again"
54
- opts.string "--report", "output file for the report (valid extensions: #{HowIs.supported_formats.join(', ')}; default: #{DEFAULT_REPORT_FILE})"
55
- opts.bool "-v", "--version", "prints the version"
56
-
57
- # Parse the arguments.
58
- parser = Slop::Parser.new(opts)
59
- result = parser.parse(argv)
60
-
61
- # +options+ is a Hash of flags/values.
62
- options = result.to_hash
63
- # +arguments+ is an Array of values that don't correspond to a flag.
64
- arguments = result.arguments
65
-
66
- # If --report isn't specified, default to DEFAULT_REPORT_FILE.
67
- options[:report] ||= DEFAULT_REPORT_FILE
68
-
69
- # The following are only useful if they're not nil or false.
70
- # Removing them here simplifies contracts and keyword args for
71
- # other APIs.
72
- options.delete(:config) unless options[:config]
73
- options.delete(:help) unless options[:help]
74
- options.delete(:version) unless options[:version]
75
-
76
- # If we can't export to the specified file, raise an exception.
77
- unless HowIs.can_export_to?(options[:report])
78
- raise InvalidOutputFileError, "Invalid file: #{options[:report_file]}. Supported formats: #{HowIs.supported_formats.join(', ')}"
79
- end
42
+ EOF
43
+
44
+ opts.separator ""
45
+ opts.separator "Options:"
46
+
47
+ # Allowed arguments:
48
+ opts.bool "-h", "--help", "Print help text"
49
+ opts.string "--config", "YAML config file, used to generate a group of reports"
50
+ opts.string "--from", "JSON report file, used instead of fetching the data again"
51
+ opts.string "--report", "output file for the report (valid extensions: #{HowIs.supported_formats.join(', ')}; default: #{DEFAULT_REPORT_FILE})"
52
+ opts.bool "-v", "--version", "prints the version"
53
+
54
+ # Parse the arguments.
55
+ parser = Slop::Parser.new(opts)
56
+ result = parser.parse(argv)
57
+
58
+ # +options+ is a Hash of flags/values.
59
+ options = result.to_hash
60
+ # +arguments+ is an Array of values that don't correspond to a flag.
61
+ arguments = result.arguments
62
+
63
+ # If --report isn't specified, default to DEFAULT_REPORT_FILE.
64
+ options[:report] ||= DEFAULT_REPORT_FILE
65
+
66
+ # The following are only useful if they're not nil or false.
67
+ # Removing them here simplifies contracts and keyword args for
68
+ # other APIs.
69
+ options.delete(:config) unless options[:config]
70
+ options.delete(:help) unless options[:help]
71
+ options.delete(:version) unless options[:version]
72
+
73
+ # If we can't export to the specified file, raise an exception.
74
+ unless HowIs.can_export_to?(options[:report])
75
+ raise InvalidOutputFileError, "Invalid file: #{options[:report]}. Supported formats: #{HowIs.supported_formats.join(', ')}"
76
+ end
80
77
 
81
- # If we pass --config, other options (excluding --help and
82
- # --version) are ignored. As such, when --config is passed,
83
- # everything in this `unless` block is irrelevant.
84
- unless options[:config]
85
- if options[:from]
86
- raise InvalidInputFileError, "No such file: #{options[:from]}" unless File.file?(options[:from])
78
+ # If we pass --config, other options (excluding --help and
79
+ # --version) are ignored. As such, when --config is passed,
80
+ # everything in this `unless` block is irrelevant.
81
+ unless options[:config]
82
+ if options[:from]
83
+ raise InvalidInputFileError, "No such file: #{options[:from]}" unless File.file?(options[:from])
87
84
 
88
- # Opening the file here is a bit gross, but I couldn't find a
89
- # better way to do it. -@duckinator
90
- options[:repository] = JSON.parse(open(options[:from]).read)['repository']
85
+ # Opening the file here is a bit gross, but I couldn't find a
86
+ # better way to do it. -@duckinator
87
+ options[:repository] = JSON.parse(open(options[:from]).read)['repository']
91
88
 
92
- raise InvalidInputFileError, "Invalid JSON report file." unless options[:repository]
89
+ raise InvalidInputFileError, "Invalid JSON report file." unless options[:repository]
93
90
 
94
- elsif argv.length >= 1
95
- options[:repository] = argv.delete_at(0)
91
+ elsif argv.length >= 1
92
+ options[:repository] = argv.delete_at(0)
96
93
 
97
- else
98
- raise NoRepositoryError, "No repository specified."
99
- end
94
+ else
95
+ raise NoRepositoryError, "No repository specified."
100
96
  end
101
-
102
- # Return a Hash with:
103
- # +opts+: the original Slop::Options object.
104
- # +options+: the Hash of flags/values (e.g. +--foo bar+ becomes
105
- # +options[:foo]+ with the value of +"bar"+).
106
- # +arguments+: an Array of arguments that don't have a
107
- # corresponding flags.
108
- {
109
- opts: opts,
110
- options: options,
111
- arguments: arguments,
112
- }
113
97
  end
98
+
99
+ # Return a Hash with:
100
+ # +opts+: the original Slop::Options object.
101
+ # +options+: the Hash of flags/values (e.g. +--foo bar+ becomes
102
+ # +options[:foo]+ with the value of +"bar"+).
103
+ # +arguments+: an Array of arguments that don't have a
104
+ # corresponding flags.
105
+ {
106
+ opts: opts,
107
+ options: options,
108
+ arguments: arguments,
109
+ }
114
110
  end
115
111
  end
@@ -43,7 +43,7 @@ class HowIs
43
43
  ##
44
44
  # Returns the format of report this class generates.
45
45
  #
46
- # @returns [Symbol] A lowercase symbol denoting the report format.
46
+ # @return [Symbol] A lowercase symbol denoting the report format.
47
47
  def format
48
48
  raise NotImplementedError
49
49
  end
data/lib/how_is/report.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'date'
2
+ require "pathname"
2
3
 
3
4
  class HowIs
4
5
  class UnsupportedExportFormat < StandardError
@@ -28,6 +29,40 @@ class HowIs
28
29
  report.export
29
30
  end
30
31
 
32
+ ##
33
+ # Saves given Report in given file.
34
+ #
35
+ # @param file [String,Pathname] Name of file to write to
36
+ # @param report [Report] Report to store
37
+ def self.save_report(file, report)
38
+ File.open(file, 'w') do |f|
39
+ f.write report
40
+ end
41
+ end
42
+
43
+ ##
44
+ # Returns the report format for given filename.
45
+ #
46
+ # @param file [String] Filename of a report
47
+ #
48
+ # @return [String] Report format inferred from file name
49
+ def self.infer_format(file)
50
+ Pathname(file).extname.delete('.')
51
+ end
52
+
53
+ ##
54
+ # Exports given +report+ to the format suitable for given +file+.
55
+ #
56
+ # @param file [String,Pathname]
57
+ # @param report [Report]
58
+ #
59
+ # @return [String] The rendered report
60
+ def self.to_format_based_on(file, report)
61
+ report_format = infer_format(file)
62
+
63
+ report.public_send("to_#{report_format}")
64
+ end
65
+
31
66
  private
32
67
  # Given a format name (+format+), returns the corresponding <blah>Report
33
68
  # class.
@@ -1,3 +1,3 @@
1
1
  class HowIs
2
- VERSION = "18.0.2"
2
+ VERSION = "18.0.3"
3
3
  end
data/lib/how_is.rb CHANGED
@@ -33,7 +33,7 @@ class HowIs
33
33
  ##
34
34
  # Generate an HTML report.
35
35
  #
36
- # @returns [String] An HTML report.
36
+ # @return [String] An HTML report.
37
37
  def to_html
38
38
  Report.export(@analysis, :html)
39
39
  end
@@ -41,7 +41,7 @@ class HowIs
41
41
  ##
42
42
  # Generate a JSON report.
43
43
  #
44
- # @returns [String] A JSON report.
44
+ # @return [String] A JSON report.
45
45
  def to_json
46
46
  Report.export(@analysis, :json)
47
47
  end
@@ -51,7 +51,7 @@ class HowIs
51
51
  # reports).
52
52
  #
53
53
  # @param json [String] A JSON report object.
54
- # @returns [HowIs] A HowIs object that can be used for generating other
54
+ # @return [HowIs] A HowIs object that can be used for generating other
55
55
  # reports, treating the JSON report as a cache.
56
56
  def self.from_json(json)
57
57
  self.from_hash(JSON.parse(json))
@@ -62,7 +62,7 @@ class HowIs
62
62
  # other reports).
63
63
  #
64
64
  # @param data [Hash] A hash containing report data.
65
- # @returns [HowIs] A HowIs object that can be used for generating other
65
+ # @return [HowIs] A HowIs object that can be used for generating other
66
66
  # reports, treating the provided report data as a cache.
67
67
  def self.from_hash(data)
68
68
  analysis = HowIs::Analyzer.from_hash(data)
@@ -73,7 +73,7 @@ class HowIs
73
73
  ##
74
74
  # Returns a list of possible export formats.
75
75
  #
76
- # @returns [Array<String>] An array of the types of reports you can
76
+ # @return [Array<String>] An array of the types of reports you can
77
77
  # generate.
78
78
  def self.supported_formats
79
79
  report_constants = HowIs.constants.grep(/.Report/) - [:BaseReport]
@@ -84,7 +84,7 @@ class HowIs
84
84
  # Returns whether or not the specified +file+ can be exported to.
85
85
  #
86
86
  # @param file [String] A filename.
87
- # @returns [Boolean] +true+ if HowIs can export to the file, +false+
87
+ # @return [Boolean] +true+ if HowIs can export to the file, +false+
88
88
  # if it can't.
89
89
  def self.can_export_to?(file)
90
90
  # TODO: Check if the file is writable?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: how_is
3
3
  version: !ruby/object:Gem::Version
4
- version: 18.0.2
4
+ version: 18.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ellen Marie Dash
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-05 00:00:00.000000000 Z
11
+ date: 2017-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: github_api
@@ -159,7 +159,9 @@ extensions: []
159
159
  extra_rdoc_files: []
160
160
  files:
161
161
  - ".gitignore"
162
+ - ".hound.yml"
162
163
  - ".rspec"
164
+ - ".rubocop.yml"
163
165
  - ".travis.yml"
164
166
  - CHANGELOG.md
165
167
  - CODE_OF_CONDUCT.md
@@ -209,7 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
209
211
  version: '0'
210
212
  requirements: []
211
213
  rubyforge_project:
212
- rubygems_version: 2.4.5.2
214
+ rubygems_version: 2.6.8
213
215
  signing_key:
214
216
  specification_version: 4
215
217
  summary: Quantify the health of a GitHub repository.