Puppet ensurable - Is it possible to wire exists? method to anything other than present or absent? - puppet

I have passed a block to the ensurable method and defined acceptable property values as well as the methods of the provider that are to be called. I understand that present and absent property depend on the result of the exist? method and depending on it they will be called/not called. However, I have a case where I also want other actions (my_action1, my_action2) to also depend on exists? result, is it possible to achieve that?
ensurable do
newvalue(:present) do
provider.create
end
newvalue(:absent) do
provider.destroy
end
newvalue(:my_action1) do
provider.my_action1
end
newvalue(:my_action2) do
provider.my_action2
end
end

Related

Using predeclared classes in VBA as namespaces

One of my biggest issues with coding in VBA is a total lack of namespaces making it difficult to ensure things like scoping and selecting the right function when every function of the same name is in the global namcespace. I know you can prefix your function calls with the module name it is in, but it seems to me that this is also possible by replacing all your modules by predeclared classes. A namespace would look something like this:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "MyNamespace"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'#Folder("Project.Namespace")
Option Explicit
Public Function Foo() As String
Foo = "bar"
End Function
' Opionally make sure users do not use this as a class
Private Sub Class_Initialize()
If Not Me Is MyNamespace Then
Err.Raise 512, _
Source:="MyNamespace.Initialize", _
Description:="Cannot create an instance of a namespace."
End If
End Sub
Thus if you ever want to call Foo in this namespace you have to write
MyNamespace.Foo()
While simply calling Foo() will not work.
My question is this:
Is there any reason you wouldn't want to do this? As far as I can see the class' constructor is only called the first time you call any of its functions after you open your project, so I can't see any overhead there, but there could be something sneaky I am not aware of. Of course this is in no way an ideal way of addressing this lack of functionality, but it is not as if VBA programmers aren't already using the language in roundabout ways to provide lacking functionality.
Also, I see that this is basically the same as this question, however I'd further want to know whether there are any specific issues with having a ton of predeclared "empty" classes in your code. Say you replace 100 modules with 100 predeclared classes, will that have any significant impact on e.g. performance/stability/etc...?
It costs you an object pointer, is all. I wouldn't call it a namespace though.
Every single UserForm module you've ever worked with has a VB_PredeclaredId attribute set to True. This instance is automatically created, as you noticed, and while you can explicitly destroy it, the next time it's referenced it'll be automatically (silently) re-created again... with whatever the original state is/was... pretty much like an auto-instantiated object, aka an As New declaration.
So what you have there is more like an object hierarchy than a namespace structure - very, very similar to how you can drill down the Excel object model starting with Application, and go do this:
Set someCell = Excel.Application.Workbooks(1).Worksheets(1).Range("A1")
Here the "namespace" is the Excel library, Application is the root object, and the rest of that expression is all member access - property getters, named after classes.
But the classes aren't in "namespaces"... the Worksheets collection type (class) exists on its own, under the Excel library: there being a Worksheets property on the Application class does not in any way, shape, or form, shield the class from a "name collision": if your user code has a class module named Worksheets (and it very well can), then as per how VBA resolves identifier references, Dim foo As Worksheet is going to be an instance of that custom class: the only valid qualifier is the library name (Excel, or MyVBAProject).
So, what you have there is a reasonable approach for building a relatively complex object model structure - but it won't (can't) replace or simulate a namespace. If you find yourself making "empty" classes, reconsider your design.
As for the last question, I don't see how having 100 predeclared custom objects might be any different than a project with 100 userforms: in both cases I'd wonder if there'd be a way to trim that down and generalize/reuse components, whether they be forms or classes.
What you want to avoid, is a predeclared object that holds state - because that state is effectively global now, and you have no control over what gets to change that state, where, and when: Application.Calculation is a prime example of this.

Excel add-in with logging class: How to react to VBA state loss?

The setup
I'm developing and maintaining an Excel add-in that comes with its own tab of controls within Excel's Ribbon UI. I've come across the problem of state loss before (meaning loss of all variables with global scope, static variables, etc, which of course includes my reference to the RibbonUI). With regards to the ribbon reference I've "solved" the problem by including a "Reset Ribbon" button that restores the reference from a persistently stored pointer and then invalidates the ribbon. Although certainly not the most elegant, this part works just fine.
However, after the introduction of a logging class, the state loss issue haunts me once again. The logger is instantiated in ThisWorkbook's module:
Private Sub Workbook_Open()
Set LogToFile = SingletonFactory.getToFileLogger
End Sub
and is then put to work, for example, as follows:
Private Sub buttonReloadObjects_onAction(ByVal control As IRibbonControl)
LogToFile.trace "Event firing: buttonReloadObjects_onAction"
' more stuff happening...
invalidateRibbon ' restores ribbon object and invalidates it
End Sub
The logger is instantiated when the add-in is loaded so that I have the freedom to log whatever I want within the confines of my add-in's code. It has several logging levels like trace/debug/error/... and a couple of other methods. Usually it works just fine - until the state loss hits (usually caused by an unrelated error, followed by clicking "End").
State loss
At this point the VBA environment forgets about the very existence of my LogToFile object and nothing works any more, because every click on the ribbon controls will trigger a runtime error 91: Object variable or with block variable not set pointing to whatever line is the first to contain a reference to LogToFile.
A solution?
Now, short of doing crazy workarounds like placing
if not isObject(LogToFile) then
Set LogToFile = SingletonFactory.getToFileLogger
end if
LogToFile.trace "Message"
before any occurrence of LogToFile, the only real "solution" I was able to come up with is to wrap all my logger calls in functions (residing in a standard module) and call these functions any time I want to send something to the log. This way I could catch the missing object reference right before the object is needed and I avoid calling methods of uninstantiated objects.
However, after having everything neatly encapsulated in class modules, it strikes me as odd, maybe even wrong(?), going down this route.
So, is there a "proper" solution to the problem of a lost logger instance? Or is my suggested approach already as proper as it can get?
Note: This problem is of course not specific to logging classes. It affects all global variables, most notably my ApplicationEventClass. The issue just happens to be the most glaring with the logger due to its frequent usage around all entry points to the code.
You only need one function that either returns the original variable or resets it. If you call that function LogToFile you don't need to change any of the other code other than removing the Workbook_Open code which is then superfluous. So:
Function LogToFile() As WhateverVariableType
Static temp as WhateverVariableType
If temp is Nothing then Set temp = SingletonFactory.getToFileLogger
Set LogToFile = temp
End Function
This way you will also still benefit from Intellisense when writing the code.
Note: you may not actually need the temp variable - it depends on whether there are settings that you want persisted. If there are, you may want to reset them in the function too.

Any reason Origen::Parameter set contexts are hidden from the user?

Is there any reason the Origen::Parameters sets do not have a public method for retrieving all of the possible set ids? I do see a public method that works, though it isn't named like it is meant to be used publicly. Why is this not more visible?
[6] pry(#<PPEKit::Product>)> $dut.func._parameter_sets.ids
=> [:default,
:func_default,
:func_harvest_default,
EDIT
#Ginty, I tried your suggestion but it doesn't return the keys I am looking for. In the first sentence in the Parameter docs, the keys I am looking for are referred to 'parameter contexts'. The reason these would be useful would be to do something like this:
my_param_key = :my_param_key
if Origen.top_level.func.has_context? my_param_key
...
Specifically, I am creating parameter contexts from the information in my flow file and would like to verify that they exist before trying to access them. Essentially it is a handshake between my test flow and the test method parameters I am storing using unique (hopefully) parameter IDs/contexts.
thx
In your example, dut.func.params should return a hash-like object which contains all the parameter sets, so to get the IDs is just: dut.func.params.keys
EDIT
I see now that you want a collection containing the available contexts, but it doesn't seem like that is currently provided via an API.
I don't think there is any particular reason for that, probably hasn't been needed until now.
params.context returns the currently active context, I would recommend we add params.contexts and/or params.available_contexts to return an array of the available context names.
Origen now supports knowing the available parameter contexts.

How to avoid page-object deprecated for checkbox

I use cucumber since one year, and I am adding page-object-gem into it since few weeks.
When I execute the test, I get message :
DEPRECATION WARNING
You are calling a method named checkbox at commentPage.rb:23:in `block in delete_comment'.
This method does not exist in page-object so it is being passed to the driver.
This feature will be removed in the near future.
Please change your code to call the correct page-object method.
(I have got the same for other cases, but this "trivial" example should be easier to explain)
I search a way to avoid that, but it seems complicated.
For the test, I am checking a page, on which there is a table. Each row show a line, and I need to check the checkbox of a particular line.
My code in the pageObject:
table(:comment_list, :class => 'comments')
button(:delete, :text => "Delete")
def delete_comment (text)
self.comment_list_element.each do |row|
if row.text.include? "#{text}"
row.checkbox.set
self.delete
return true
end
end
false
end
Did I need a pretreatment of my table to use it during the test ?
You are getting the warning because you are calling a method that is on Watir and not page-object (checkbox method on a table row). If you want to access the Checkbox you can simply call the method that will return the nested element. This would change that portion of the call to row.checkbox_element. But you next call will also get the same issue. First of all the set method does not exist on CheckBox. In page-object the methods are check and uncheck. The full call should be:
row.checkbox_element.check
The reason you are getting the deprecation error is because I plan to remove the forwarding of calls to the underlying driver in the future. This ability really causes a lot of problems in complex situations.
In your code, row is a PageObject::Elements::TableRow, which does not have a checkbox method defined. I have not come across any examples where page-object elements were chained.
As a workaround, you could convert the PageObject::Elements::TableRow to a regular Watir::TableRow by doing:
row.element
So your code will work if you do:
row.element.checkbox.set

How to make function to call only when input parameters are change

I'm creating set of user defined functions, but I only need to recall these function if and only a input parameter of a partcular function is change.
Currently, even I delete/insert a row the function are being called, How can I stop this function recalling ?
Thank You
Well, you can work around it by remembering the parameters that were passed to your function. You can use some global variable (an array) where you record the parameters.
However, it does not sound very efficient.
Save the parameter(s) to Static variable(s) and exit the sub if the parameters haven't changed.

Resources