Puts not working - Anyone else?


#21

the ‘stock’ ones live in

/Users/<your user name>/Library/Application Support/SketchUp 2018/SketchUp/Plugins

the other path is on the hard drive, outside of your ‘User’ account…

I suspect whatever is in it could be the problem…

john


#22

I find this strange as puts() is defined in the Kernel module (which is mixed into Object.)

This may indicate that some script (or gem) has redefined puts() in the global ObjectSpace.


#23

Indeed! If I run that snippet I get Kernel not Object.


#24

Now that you know you are getting puts from Object, not Kernel, perhaps this snippet will find the culprit:

Object.instance_method(:puts).source_location

It should return an Array containing the file path and line number at which puts has been defined (unless it is defined in compiled code or not an instance method, in which case it returns nil).

Edit: this shorter version should also work:

method(:puts).source_location

#25
> Object.instance_method(:puts).source_location
["/library/application support/sketchup 2018/sketchup/plugins/podiumextras/nudge.rbs", 796]
> 

and

> method(:puts).source_location
["/library/application support/sketchup 2018/sketchup/plugins/podiumextras/nudge.rbs", 796]
> 

#26

And there you have it! The Podium extension is “monkey-patching” puts in the Object class. This is a good example of why modifying standard classes is considered a very bad thing.


#27

Eureka!

Changing the name of

/Library/Application Support/SketchUp 2018/SketchUp/Plugins

(not the one in my User folder)

allows puts to work.

In that Plugin folder where two folders:

  • PodiumExtras
  • SU_Podium_V2.5

and 2 files:

  • PodiumExtrasLoader.rbs
  • SU_Podium_V2.5.rbs

#28

I’ve been telling my clients either to not use podium extras or to rename nudge.rbs to nudge.rbs_ and to live with the loading error.

I sent an email to podium about the fact that they have redefined puts - but they haven’t done anything about it. They simply stated that they have lots of clients using it without problems.

Here is an example of the back trace from one of my clients

Error: #<ArgumentError: wrong number of arguments (2 for 1)>

c:/programdata/sketchup/sketchup 2018/sketchup/plugins/podiumextras/nudge.rbs:796:in `puts’

c:/users/mobil_design4/appdata/roaming/sketchup/sketchup 2018/sketchup/plugins/gkware_cabmaker2/cabmaker2.rbe:413:in `rescue in do_create_cabinet’

c:/users/mobil_design4/appdata/roaming/sketchup/sketchup 2018/sketchup/plugins/gkware_cabmaker2/cabmaker2.rbe:401:in `do_create_cabinet’

c:/users/mobil_design4/appdata/roaming/sketchup/sketchup 2018/sketchup/plugins/gkware_cabmaker2/cabmaker2.rbe:635:in `onLButtonDown’


#29

Wow… nixing podium extras also fixed an issue I was having where I would get a crash message every time I closed SU!


#30

I found this in minutes because I had set up a backtrace in a rescue.

begin
# ...
rescue StandardError => e
  puts e, e.backtrace
  UI.messagebox(e)
end

The standard puts as defined by the kernel allows you to put 1 or more statements on a line separated by commas. When nudge redefined puts they no longer allowed multiple statements


#31

Eureka !
[Or more properly ‘Eurekes’, since you found it, not ‘me’…]

Now please tell Podium immediately, so that they can fix this unfortunate, and wholly avoidable mess, asap !


#32

@tt_su, have you got a name and shame GitHub site???

john


#33

Dave Wayne from Podium has emailed me stating that they are in the midst of recompiling all their C++ code and will ask the original programmer to look into the nudge problem once they have taken care of their recompile.

BTW - my first email to them was on 6/29/2018


#34

@gkernan

Their delay shows a wilful lack of care [IMHO].
The error seems to arise from a compiled RB script, nothing to do with C++…
It’d only be a few hours work to fix that avoidable Ruby coding error, and then to reissue a new installer with the corrected nudge.RBS file…
:face_with_raised_eyebrow:


#35

This has bogged a lot of (mac)users. Though mac users usually keep SU ‘alive’ and just start a new tab instead of file->quit, they would always had to force quit SH when turning of the computer…


#36

I even provided them with a backtrace. If you look at what Hank provided - it’s the exact same line in nudge.rbs

c:/programdata/sketchup/sketchup 2018/sketchup/plugins/podiumextras/nudge.rbs:796:in `puts’


#37

The problem with monkey-patching is that you need to preserve the exact same method signature.

If the original method accepts multiple arguments you must expect someone is using that. But the opposite is also true, if the method accepts 2 arguments and you add a seemingly future-proof catch-all (*args) you will break code that is checking method arity to distinguish different Ruby or SketchUp API versions of that method.

If you target different SketchUp/Ruby versions where the original method signature changed, you need to provide an override for each version of the method signature.

That’s why poorly done overriding is dangerous and bad. I am sure what they were trying to do can be better achieved by not overriding puts but in other places with less impact. And impact of an extension should be kept as minimal as possible so that it is only active while in use (add observers when tool is activated, then remove observers; same for overriding and intercepting console).


#38

I’d go further than @Aerilius and assert that in a shared interpreter setting such as SketchUp, monkey-patching a base class or module is never necessary or acceptable. It is the embedded interpreter equivalent of creating your own version of, for example, the C-runtime library and dropping it in place the system’s library. The match has to be perfectly transparent or you will eventually break someone else’s code. And, even if it is just for you own use, it is lazy programming. For example, if you need some variant behavior of puts for your own code, you can call it my_puts and call that instead of the system puts. You don’t know when or why other people’s code might call puts, so you know what side effects your substitute will have only on your own code.


#39

There are extremely rare cases when monkey patching can be used in SketchUp. Aeriliu’s LaunchUp uses it to interpret menu entries and commands being added by other extensions, to make them searchable, and I’m using a similar approach in my tool memory to get references to custom Ruby tools. However it needs to be stated that these are quite extreme cases, when the API doesn’t allow any other way.

Generally speaking this is a huge no-no.

Edit: For the record, here is the feature request I’ve filed on the topic: https://github.com/SketchUp/api-issue-tracker/issues/10


#40

If you want only your own code to call a variant of another method (like puts), you can implement my_puts (and make it optionally forward to any core method).

But there is a use case:

If your code wants to observe when another method is called, you need an observer mechanism which Ruby does not provide (except of super-expensive set_trace_func).
There is for example also the paradigm of Aspect-Oriented Programming which is about extending behavior by attaching customized methods before or after another method (for example by a decorator pattern). It is not natively supported by Ruby, but available as a gem, which is probably realized by some sort of monkey-patching.

  • The original 2012 SketchUp Developer tools overrode Kernel.puts to catch when it is called.
  • Last time I checked, TestUp registered its own subclass of Sketchup::Console in $stdout to make it compatible for Minitest.
  • My Ruby Console registers a forwardable proxy around Sketchup::Console in $stdout only while this extension is actively used. This is to some extent safer than overriding methods because $stdout is assignable and the effect can be reversed by reassigning the original object. A forwardable allows to exactly take over other methods of the base class even if Ruby adds methods in the future. And in a similar kind, Sketchup::Console is a not 100% compatible drop-in replacement for Ruby’s #<IO:<STDOUT>>.