isort 0.2.0 → 0.2.1

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.
@@ -0,0 +1,240 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Isort
4
+ # Wrap modes for handling long import lines
5
+ module WrapModes
6
+ # Mode 0: Grid - wraps with opening parenthesis on first line
7
+ # require 'a', 'b', 'c',
8
+ # 'd', 'e'
9
+ GRID = 0
10
+
11
+ # Mode 1: Vertical - one import per line after opening paren
12
+ # require(
13
+ # 'a',
14
+ # 'b',
15
+ # 'c',
16
+ # )
17
+ VERTICAL = 1
18
+
19
+ # Mode 2: Hanging indent - continuation lines have extra indent
20
+ # require 'a', 'b', 'c',
21
+ # 'd', 'e'
22
+ HANGING_INDENT = 2
23
+
24
+ # Mode 3: Vertical hanging indent - combines vertical and hanging
25
+ # require(
26
+ # 'a',
27
+ # 'b',
28
+ # 'c',
29
+ # )
30
+ VERTICAL_HANGING_INDENT = 3
31
+
32
+ # Mode 4: Vertical grid - like grid but vertical
33
+ # require(
34
+ # 'a', 'b',
35
+ # 'c', 'd',
36
+ # )
37
+ VERTICAL_GRID = 4
38
+
39
+ # Mode 5: Vertical grid grouped - groups related imports
40
+ # require('a', 'b',
41
+ # 'c', 'd')
42
+ VERTICAL_GRID_GROUPED = 5
43
+
44
+ # Mode 6: Vertical grid grouped with trailing comma
45
+ VERTICAL_GRID_GROUPED_NO_WRAP = 6
46
+
47
+ # Mode 7: NOQA - single line with comment to disable linting
48
+ NOQA = 7
49
+
50
+ # Default mode
51
+ DEFAULT = VERTICAL_HANGING_INDENT
52
+
53
+ # All available modes
54
+ MODES = {
55
+ grid: GRID,
56
+ vertical: VERTICAL,
57
+ hanging_indent: HANGING_INDENT,
58
+ vertical_hanging_indent: VERTICAL_HANGING_INDENT,
59
+ vertical_grid: VERTICAL_GRID,
60
+ vertical_grid_grouped: VERTICAL_GRID_GROUPED,
61
+ vertical_grid_grouped_no_wrap: VERTICAL_GRID_GROUPED_NO_WRAP,
62
+ noqa: NOQA
63
+ }.freeze
64
+
65
+ class << self
66
+ # Get mode by name or number
67
+ def get(mode)
68
+ case mode
69
+ when Integer
70
+ mode
71
+ when Symbol, String
72
+ MODES[mode.to_sym] || DEFAULT
73
+ else
74
+ DEFAULT
75
+ end
76
+ end
77
+
78
+ # Format a multi-import line according to the wrap mode
79
+ # for formatting long autoload statements or future multi-require support
80
+ def format_line(imports, mode: DEFAULT, line_length: 79, indent: "")
81
+ mode = get(mode)
82
+
83
+ case mode
84
+ when GRID
85
+ format_grid(imports, line_length, indent)
86
+ when VERTICAL
87
+ format_vertical(imports, indent)
88
+ when HANGING_INDENT
89
+ format_hanging_indent(imports, line_length, indent)
90
+ when VERTICAL_HANGING_INDENT
91
+ format_vertical_hanging_indent(imports, indent)
92
+ when VERTICAL_GRID
93
+ format_vertical_grid(imports, line_length, indent)
94
+ when VERTICAL_GRID_GROUPED
95
+ format_vertical_grid_grouped(imports, line_length, indent)
96
+ when NOQA
97
+ format_noqa(imports, indent)
98
+ else
99
+ format_vertical_hanging_indent(imports, indent)
100
+ end
101
+ end
102
+
103
+ # Check if a line needs wrapping based on line length
104
+ def needs_wrapping?(line, max_length: 79)
105
+ line.length > max_length
106
+ end
107
+
108
+ # Split a long import line into multiple lines
109
+ # Currently used for comments/documentation, as Ruby imports are typically single-line
110
+ def wrap_comment(comment, max_length: 79, indent: "")
111
+ return [comment] if comment.length <= max_length
112
+
113
+ words = comment.split(/\s+/)
114
+ lines = []
115
+ current_line = indent.dup
116
+
117
+ words.each do |word|
118
+ if current_line.length + word.length + 1 > max_length && current_line != indent
119
+ lines << current_line.rstrip
120
+ current_line = "#{indent}# #{word}"
121
+ else
122
+ current_line += current_line == indent ? "# #{word}" : " #{word}"
123
+ end
124
+ end
125
+
126
+ lines << current_line.rstrip unless current_line.strip.empty?
127
+ lines
128
+ end
129
+
130
+ private
131
+
132
+ def format_grid(imports, line_length, indent)
133
+ return imports.first if imports.size == 1
134
+
135
+ lines = []
136
+ current_line = indent.dup
137
+
138
+ imports.each_with_index do |imp, idx|
139
+ separator = idx < imports.size - 1 ? ", " : ""
140
+ potential = current_line + imp + separator
141
+
142
+ if potential.length > line_length && current_line != indent
143
+ lines << current_line.rstrip.chomp(",")
144
+ current_line = "#{indent}#{imp}#{separator}"
145
+ else
146
+ current_line = potential
147
+ end
148
+ end
149
+
150
+ lines << current_line.rstrip
151
+ lines.join("\n")
152
+ end
153
+
154
+ def format_vertical(imports, indent)
155
+ inner_indent = "#{indent} "
156
+ result = ["#{indent}("]
157
+ imports.each do |imp|
158
+ result << "#{inner_indent}#{imp},"
159
+ end
160
+ result << "#{indent})"
161
+ result.join("\n")
162
+ end
163
+
164
+ def format_hanging_indent(imports, line_length, indent)
165
+ continuation_indent = "#{indent} "
166
+ lines = []
167
+ current_line = indent.dup
168
+
169
+ imports.each_with_index do |imp, idx|
170
+ separator = idx < imports.size - 1 ? ", " : ""
171
+
172
+ if idx == 0
173
+ current_line += imp + separator
174
+ elsif current_line.length + imp.length + separator.length > line_length
175
+ lines << current_line.rstrip.chomp(",")
176
+ current_line = "#{continuation_indent}#{imp}#{separator}"
177
+ else
178
+ current_line += imp + separator
179
+ end
180
+ end
181
+
182
+ lines << current_line.rstrip
183
+ lines.join("\n")
184
+ end
185
+
186
+ def format_vertical_hanging_indent(imports, indent)
187
+ inner_indent = "#{indent} "
188
+ result = ["#{indent}("]
189
+ imports.each do |imp|
190
+ result << "#{inner_indent}#{imp},"
191
+ end
192
+ result << "#{indent})"
193
+ result.join("\n")
194
+ end
195
+
196
+ def format_vertical_grid(imports, line_length, indent)
197
+ inner_indent = "#{indent} "
198
+ result = ["#{indent}("]
199
+ current_line = inner_indent.dup
200
+
201
+ imports.each_with_index do |imp, idx|
202
+ separator = idx < imports.size - 1 ? ", " : ","
203
+
204
+ if current_line.length + imp.length + separator.length > line_length && current_line != inner_indent
205
+ result << current_line.rstrip
206
+ current_line = "#{inner_indent}#{imp}#{separator}"
207
+ else
208
+ current_line += current_line == inner_indent ? "#{imp}#{separator}" : " #{imp}#{separator}"
209
+ end
210
+ end
211
+
212
+ result << current_line.rstrip unless current_line.strip.empty?
213
+ result << "#{indent})"
214
+ result.join("\n")
215
+ end
216
+
217
+ def format_vertical_grid_grouped(imports, line_length, indent)
218
+ inner_indent = "#{indent} "
219
+ current_line = "#{indent}("
220
+
221
+ imports.each_with_index do |imp, idx|
222
+ separator = idx < imports.size - 1 ? ", " : ""
223
+
224
+ if current_line.length + imp.length + separator.length > line_length
225
+ current_line += "\n#{inner_indent}#{imp}#{separator}"
226
+ else
227
+ current_line += imp + separator
228
+ end
229
+ end
230
+
231
+ current_line + ")"
232
+ end
233
+
234
+ def format_noqa(imports, indent)
235
+ line = imports.join(", ")
236
+ "#{indent}#{line} # noqa"
237
+ end
238
+ end
239
+ end
240
+ end
data/test_local.rb ADDED
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Quick script to test isort locally
5
+ # Usage: bundle exec ruby test_local.rb
6
+
7
+ $LOAD_PATH.unshift File.expand_path("lib", __dir__)
8
+ require "isort"
9
+ require "tempfile"
10
+
11
+ puts "=" * 60
12
+ puts "Testing isort locally"
13
+ puts "=" * 60
14
+
15
+ # Create a test file with unsorted imports
16
+ test_content = <<~RUBY
17
+ require 'yaml'
18
+ require_relative 'helper'
19
+ require 'json'
20
+ include Enumerable
21
+ require 'csv'
22
+ extend ActiveSupport::Concern
23
+ require_relative 'version'
24
+
25
+ class MyApp
26
+ def run
27
+ puts "Hello"
28
+ end
29
+ end
30
+ RUBY
31
+
32
+ tempfile = Tempfile.new(["test_isort", ".rb"])
33
+ tempfile.write(test_content)
34
+ tempfile.flush
35
+
36
+ puts "\nšŸ“„ Original file:"
37
+ puts "-" * 40
38
+ puts test_content
39
+
40
+ puts "\nšŸ” Running --check mode:"
41
+ puts "-" * 40
42
+ processor = Isort::FileProcessor.new(tempfile.path)
43
+ would_change = processor.check
44
+ puts would_change ? "File needs sorting" : "File is already sorted"
45
+
46
+ puts "\nšŸ“ Running --diff mode:"
47
+ puts "-" * 40
48
+ diff_output = processor.diff
49
+ if diff_output
50
+ puts diff_output
51
+ else
52
+ puts "No changes needed"
53
+ end
54
+
55
+ puts "\nāœ… Running sort:"
56
+ puts "-" * 40
57
+ processor2 = Isort::FileProcessor.new(tempfile.path)
58
+ changed = processor2.process
59
+
60
+ puts "\nšŸ“„ Sorted file:"
61
+ puts "-" * 40
62
+ puts File.read(tempfile.path)
63
+
64
+ puts "\nšŸ”„ Testing idempotency (running again):"
65
+ puts "-" * 40
66
+ processor3 = Isort::FileProcessor.new(tempfile.path)
67
+ changed_again = processor3.process
68
+ puts changed_again ? "File changed (NOT idempotent!)" : "No changes (idempotent āœ“)"
69
+
70
+ # Test skip directive
71
+ puts "\n🚫 Testing skip directive:"
72
+ puts "-" * 40
73
+ skip_content = <<~RUBY
74
+ require 'yaml' # isort:skip
75
+ require 'json'
76
+ require 'csv'
77
+ RUBY
78
+
79
+ tempfile2 = Tempfile.new(["test_skip", ".rb"])
80
+ tempfile2.write(skip_content)
81
+ tempfile2.flush
82
+
83
+ puts "Original:"
84
+ puts skip_content
85
+ Isort::FileProcessor.new(tempfile2.path).process
86
+ puts "\nAfter sorting (yaml should stay first due to skip):"
87
+ puts File.read(tempfile2.path)
88
+
89
+ # Test section-based grouping
90
+ puts "\nšŸ“¦ Section-based grouping:"
91
+ puts "-" * 40
92
+ puts "Imports are grouped by section:"
93
+ puts " 1. stdlib (json, csv, yaml...)"
94
+ puts " 2. thirdparty (rails, active_support...)"
95
+ puts " 3. firstparty (include, extend, autoload, using)"
96
+ puts " 4. localfolder (require_relative)"
97
+
98
+ # Cleanup
99
+ tempfile.close
100
+ tempfile.unlink
101
+ tempfile2.close
102
+ tempfile2.unlink
103
+
104
+ puts "\n" + "=" * 60
105
+ puts "All tests completed!"
106
+ puts "=" * 60
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: isort
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - abhinvv1
@@ -87,11 +87,20 @@ files:
87
87
  - README.md
88
88
  - Rakefile
89
89
  - exe/isort
90
+ - isort-0.2.0.gem
90
91
  - lib/isort.rb
92
+ - lib/isort/file_processor.rb
93
+ - lib/isort/import_block.rb
94
+ - lib/isort/import_statement.rb
95
+ - lib/isort/parser.rb
96
+ - lib/isort/section.rb
97
+ - lib/isort/syntax_validator.rb
91
98
  - lib/isort/version.rb
99
+ - lib/isort/wrap_modes.rb
92
100
  - sample.rb
93
101
  - sig/isort.rbs
94
102
  - sig/isort/file_sorter.rbs
103
+ - test_local.rb
95
104
  homepage: https://github.com/abhinvv1/isort
96
105
  licenses:
97
106
  - MIT
@@ -99,6 +108,7 @@ metadata:
99
108
  homepage_uri: https://github.com/abhinvv1/isort
100
109
  source_code_uri: https://github.com/abhinvv1/isort
101
110
  changelog_uri: https://github.com/abhinvv1/isort
111
+ github_repo: ssh://github.com/abhinvv1/isort
102
112
  post_install_message:
103
113
  rdoc_options: []
104
114
  require_paths: