Permalink
Browse files

Initial commit, and probably first release

  • Loading branch information...
0 parents commit f51f44c0746412fb382c51954231c5854a7729d6 @raggi committed Dec 29, 2008
@@ -0,0 +1,4 @@
+== 0.1.0 / 2008-12-24
+
+* 1 major enhancement
+ * Birthday!
@@ -0,0 +1,20 @@
+History.txt
+Manifest.txt
+README.txt
+Rakefile
+lib/exception_string.rb
+spec/.bacon
+spec/helper.rb
+spec/runner
+spec/spec_exception_string.rb
+tasks/ann.rake
+tasks/autospec.rake
+tasks/bones.rake
+tasks/gem.rake
+tasks/git.rake
+tasks/manifest.rake
+tasks/notes.rake
+tasks/post_load.rake
+tasks/rdoc.rake
+tasks/rubyforge.rake
+tasks/setup.rb
@@ -0,0 +1,80 @@
+exception_string
+ by James Tucker
+ http://ra66i.org
+ http://github.com/raggi/exception_string
+
+== DESCRIPTION:
+
+Provides clean exception formatting as a string, which resembles native output
+formats for back-traces that kill the interpreter. Whilst there are shorter,
+simpler ways to format ruby exceptions, this format is almost as short, but
+provides the format that young ruby programmers will be familiar with, and can
+be used to keep logs and output data consistent with other areas of the
+platform.
+
+At present the only provided format is that which is generated by MRI 1.8.x.
+
+== FEATURES/PROBLEMS:
+
+* Supports MRI (ruby 1.8.x) style exception formats
+* Kinda a big package, for 3 LoC.
+* Should probably be part of the platform.
+
+== SYNOPSIS:
+
+Something like:
+
+ ...
+
+ begin
+ raise "boom"
+ rescue => e
+ puts e.to_s_mri
+ end
+
+ ...
+
+Outputs something like:
+
+ boomtest.rb:18:in `go': boom (RuntimeError)
+ from boomtest.rb:34:in `foo'
+ from boomtest.rb:36
+
+
+== REQUIREMENTS:
+
+* Ruby!
+* bacon for the spec suite
+
+== INSTALL:
+
+* gem install exception_string
+
+== TODO:
+
+* Add other interpreter exception formats, if there are any variances.
+
+== LICENSE:
+
+(The MIT License)
+
+Copyright (c) 2008 James Tucker
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,22 @@
+# Look in the tasks/setup.rb file for the various options that can be
+# configured in this Rakefile. The .rake files in the tasks directory
+# are where the options are used.
+
+load 'tasks/setup.rb'
+
+ensure_in_path 'lib'
+require 'exception_string'
+
+task :default => :test
+
+PROJ.name = 'exception_string'
+PROJ.authors = 'James Tucker'
+PROJ.email = 'raggi@rubyforge.org'
+PROJ.url = 'http://github.com/raggi/exception_string'
+PROJ.rubyforge.name = 'raggi'
+PROJ.version = ExceptionString.version
+
+PROJ.exclude = %w(tmp$ bak$ ~$ CVS \.git \.hg \.svn ^pkg ^doc \.DS_Store
+ \.cvs \.svn \.hgignore \.gitignore \.dotest \.swp$ ~$)
+
+# EOF
@@ -0,0 +1,25 @@
+module ExceptionString
+
+ Version = VERSION = '0.1.0'
+
+ def self.version
+ Version
+ end
+
+ # Formats exception data in a manner that appears the same as MRI outputs
+ # for uncaught exceptions.
+ # e.g.
+ # boomtest.rb:18:in `go': boom (RuntimeError)
+ # from boomtest.rb:34:in `foo'
+ # from boomtest.rb:36
+ def to_s_mri
+ ["#{backtrace[0,1]}: #{message} (#{self.class.name})",
+ backtrace[1..-1]
+ ].flatten.join "\n\tfrom "
+ end
+
+end
+
+class Exception
+ include ExceptionString
+end
No changes.
@@ -0,0 +1,16 @@
+# Disable test/unit and rspec from running, in case loaded by broken tools.
+Test::Unit.run = false if defined?(Test) && defined?(Test::Unit)
+Spec::run = false if defined?(Spec) && Spec::respond_to?(:run=)
+
+# Setup a nice testing environment
+$DEBUG, $TESTING = true, true
+$:.push File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
+$:.uniq!
+
+%w[rubygems bacon].each { |r| require r }
+
+# Bacon doesn't do any automagic, so lets tell it to!
+Bacon.summary_on_exit
+
+require File.expand_path(
+ File.join(File.dirname(__FILE__), %w[.. lib exception_string]))
@@ -0,0 +1,9 @@
+#!/usr/bin/env ruby
+__DIR__ = File.dirname(__FILE__)
+__APP__ = File.expand_path(__DIR__ + '/../')
+
+puts
+Dir.chdir(__APP__) do
+ files = ARGV.empty? ? Dir.glob('{test,spec}/**/{test,spec}_*.rb') : ARGV
+ files.each { |f| require f }
+end
@@ -0,0 +1,38 @@
+require File.dirname(__FILE__) + '/helper'
+
+require 'rbconfig'
+
+class Runner
+ attr_accessor :ruby, :lib
+
+ def initialize(config)
+ @ruby = File.expand_path(File.join(config['bindir'], config['ruby_install_name']))
+ @lib = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'exception_string.rb'))
+ end
+
+ def exec(code, *libs)
+ libs.map! { |l| "-r#{l}" }
+ %x(#{ruby} #{libs} -e "#{code}" 2>&1)
+ end
+end
+
+describe "Exception#to_s_mri" do
+ before do
+ @code ||= "def foo; raise 'my crazy boom'; end; foo"
+ @safe_code = "begin; #{@code}; rescue => e; abort(e.to_s_mri); end"
+ @helper = Runner.new(Config::CONFIG)
+ end
+
+ should "have a format that appears the same as the native exception" do
+ native = @helper.exec(@code)
+ generated = @helper.exec(@safe_code, @helper.lib)
+ generated.should.eql(native)
+ end
+
+ should "contain the backtrace" do
+ output = @helper.exec(@safe_code, @helper.lib)
+ output.should.match(/in `foo'/)
+ output.should.match(/from -e\:1/)
+ output.should.match(/my crazy boom/)
+ end
+end
@@ -0,0 +1,81 @@
+# $Id$
+
+begin
+ require 'bones/smtp_tls'
+rescue LoadError
+ require 'net/smtp'
+end
+require 'time'
+
+namespace :ann do
+
+ # A prerequisites task that all other tasks depend upon
+ task :prereqs
+
+ file PROJ.ann.file do
+ ann = PROJ.ann
+ puts "Generating #{ann.file}"
+ File.open(ann.file,'w') do |fd|
+ fd.puts("#{PROJ.name} version #{PROJ.version}")
+ fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
+ fd.puts(" #{PROJ.url}") if PROJ.url.valid?
+ fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
+ fd.puts
+ fd.puts("== DESCRIPTION")
+ fd.puts
+ fd.puts(PROJ.description)
+ fd.puts
+ fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
+ fd.puts
+ ann.paragraphs.each do |p|
+ fd.puts "== #{p.upcase}"
+ fd.puts
+ fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
+ fd.puts
+ end
+ fd.puts ann.text if ann.text
+ end
+ end
+
+ desc "Create an announcement file"
+ task :announcement => ['ann:prereqs', PROJ.ann.file]
+
+ desc "Send an email announcement"
+ task :email => ['ann:prereqs', PROJ.ann.file] do
+ ann = PROJ.ann
+ from = ann.email[:from] || PROJ.email
+ to = Array(ann.email[:to])
+
+ ### build a mail header for RFC 822
+ rfc822msg = "From: #{from}\n"
+ rfc822msg << "To: #{to.join(',')}\n"
+ rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
+ rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
+ rfc822msg << "\n"
+ rfc822msg << "Date: #{Time.new.rfc822}\n"
+ rfc822msg << "Message-Id: "
+ rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
+ rfc822msg << File.read(ann.file)
+
+ params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
+ ann.email[key]
+ end
+
+ params[3] = PROJ.email if params[3].nil?
+
+ if params[4].nil?
+ STDOUT.write "Please enter your e-mail password (#{params[3]}): "
+ params[4] = STDIN.gets.chomp
+ end
+
+ ### send email
+ Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
+ end
+end # namespace :ann
+
+desc 'Alias to ann:announcement'
+task :ann => 'ann:announcement'
+
+CLOBBER << PROJ.ann.file
+
+# EOF
@@ -0,0 +1,33 @@
+# Poor mans autotest, for when you absolutely positively, just need an autotest.
+# N.B. Uses a runner under test/ or spec/, so you can customize the runtime.
+# Thanks to manveru for this!
+desc "Run specs every time a file changes in lib or spec"
+task :autospec do
+ rb = Gem.ruby rescue nil
+ rb ||= (require 'rbconfig'; File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']))
+ command = 'spec/runner' if test ?e, 'spec/runner'
+ command ||= 'test/runner' if test ?e, 'test/runner'
+ files = Dir.glob('{lib,spec,test}/**/*.rb')
+ mtimes = {}
+ sigtrap = proc { puts "\rDo that again, I dare you!"; trap(:INT){ exit 0 }; sleep 0.8; trap(:INT, &sigtrap) }
+ trap(:INT, &sigtrap)
+ system "#{rb} -I#{GSpec.require_path} #{command}"
+ while file = files.shift
+ begin
+ mtime = File.mtime(file)
+ mtimes[file] ||= mtime
+ if mtime > mtimes[file]
+ files = Dir.glob('{lib,spec,test}/**/*.rb') - [file] # refresh the file list.
+ puts
+ system "#{rb} -I#{GSpec.require_path} #{command} #{file}"
+ puts
+ end
+ mtimes[file] = mtime
+ files << file
+ rescue Exception
+ retry
+ end
+ # print "\rChecking: #{file.ljust((ENV['COLUMNS']||80)-11)}";$stdout.flush
+ sleep 0.2
+ end
+end
@@ -0,0 +1,5 @@
+task :spec do
+ ruby 'spec/runner'
+end
+
+task :test => :spec
@@ -0,0 +1,21 @@
+# $Id$
+
+if HAVE_BONES
+
+namespace :bones do
+
+ desc 'Show the PROJ open struct'
+ task :debug do |t|
+ atr = if t.application.top_level_tasks.length == 2
+ t.application.top_level_tasks.pop
+ end
+
+ if atr then Bones::Debug.show_attr(PROJ, atr)
+ else Bones::Debug.show PROJ end
+ end
+
+end # namespace :bones
+
+end # HAVE_BONES
+
+# EOF
Oops, something went wrong.

0 comments on commit f51f44c

Please sign in to comment.