Skip to content

Allow inheritance/composition when creating custom scripts #9420

@kkthxbye-code

Description

@kkthxbye-code

NetBox version

v3.2.3

Feature type

Change to existing functionality

Proposed functionality

I would like to be able to do the following:

class BaseTestScript:
    test = BooleanVar(label="This is a test!")

    def shared_function(self):
        pass

class FancyTestScript(BaseTestScript, Script):
    class Meta:
        name = "Fancy testing"
        commit_default = True
   
    def run(self, data, commit):
        is_test = self.data['test']
        
        if is_test:
            self.log_success("test!")

class AwesomeTestScript(BaseTestScript, Script):
    class Meta:
        name = "Awesome testing"
        commit_default = True
   
    def run(self, data, commit):
        is_test = self.data['test']
        
        if is_test:
            self.log_failure("test!")

This currently doesn't work. The script is recognized, but none of the ScriptVars are present. The reason is here:

def _get_vars(cls):
vars = {}
for name, attr in cls.__dict__.items():
if name not in vars and issubclass(attr.__class__, ScriptVariable):
vars[name] = attr

__dict__ only contains attributes of the class itself, without attributes inherited from base classes.

I propose changing the code to:

# Iterate all base classes looking for ScriptVariables
for base_class in inspect.getmro(cls):
    for name, attr in base_class.__dict__.items():
        if name not in vars and issubclass(attr.__class__, ScriptVariable):
            vars[name] = attr

It will search all base classes for subclasses of ScriptVariable. From quick testing it seemed to work great without breaking existing scripts. If accepted I will provide the implementation.

Use case

Managing a lot of scripts is tedious and duplication of code is hard to avoid. Allowing to define base classes which can be extended to provide scripts that have similar but different functionality would help in keeping stuff clean and maintainable.

Database changes

None

External dependencies

None

Metadata

Metadata

Assignees

Labels

status: acceptedThis issue has been accepted for implementationtype: featureIntroduction of new functionality to the application

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions