Skip to content

Commit 62bf23b

Browse files
committed
change import statements and updated install script
change import statements and updated install script to support both python2 and python3 virtual environments The change in the import statements is required to allow the extension to run properly under the python3 virtual environment for Klipper Install script was updated and reorganized; Added the following functions to the install script: validate_printer_config_dir function, change_printer_config_dir function, check_env_version, validate_python3_installed, change_py3, check_existing, create_requirements_file, prompt_user_update, validate_user_response, copy_moonraker_update_file, and create_moonraker_file Since this install script must handle both python2 and python3 virtual environments the install script will generate the following files while the script is running based on the version of python running in Klipper virtual environment: requirements.txt and extended_template_update.conf The install script will now prompt the user to see if they want this extension automatically updated via moonraker's update manager. If they answer Yes, then the install script will append an [include statement] to the EOF for the moonraker.conf and save the extended_template_update.conf file to the printer's config directory. Since moonraker changed directory structures, this install script will validate the printer's config file directory. If the user is in python2 virtual env then the printer config directory should be /home/pi/klipper_config If the user is in python3 virtual env then the printer config directory should be /home/pi/printer_data/config This script defaults to a printer config directory of /home/pi/printer_data/config Since this install script can now detect when this extension has already been installed, then need for another script file for updates in no longer necessary. This install scripts' function called check_existing will produce a 1 if the symbolic links to the .py files already exists. If the symbolic links are not present then check_existing will return a 0. This logic is used to stop the script reinstalling the additional software packages after this extension has been installed. Since the moonraker update manager will automatically restart Klipper after an update, this script prevents Klipper from restarting once the extension has been installed. When an moonraker update does occur this script will re-verify all the directories and refresh the symbolic links to this extensions .py files. choose a different instantance variable name for the class in the module Removed unnecessary spaces from the files ensure the execute bit is set for install.sh file
1 parent 5b8d687 commit 62bf23b

File tree

7 files changed

+371
-155
lines changed

7 files changed

+371
-155
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
.vscode
12
.old
23
**.pyc

extended_macro/delayed_extended.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
#
99

1010
import logging
11-
import delayed_gcode
11+
from .delayed_gcode import DelayedGcode
1212

1313
######################################################################
1414
# Extended Delayed GCode macro
1515
######################################################################
1616
#
1717
# Inherits DelayedGcode from delayed_gcode.py
1818
# Only changes the template objects
19-
class ExtendedDelayedGcode(delayed_gcode.DelayedGcode):
19+
class ExtendedDelayedGcode(DelayedGcode):
2020
def __init__(self, config):
2121
self.printer = config.get_printer()
2222
self.reactor = self.printer.get_reactor()

extended_macro/extended_macro.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def __init__(self, printer, env, name, script):
4141
raise printer.config_error(msg)
4242

4343
# Inherits PrinterGCodeMacro from gcode_macro.py
44-
# Code added to utilize
44+
# Code added to utilize
4545
class ExtendedPrinterGCodeMacro(PrinterGCodeMacro, object): #Dummy `object` required due to the Python 2 requirement for using super()
4646
def __init__(self, config):
4747
super(ExtendedPrinterGCodeMacro, self).__init__(config)

extended_macro/extended_template.py

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
import flatten_dict
77

88
# DEFAULTS
9-
# The default imports to be loaded by extended_template.
9+
# The default imports to be loaded by extended_template.
1010
# These do not need to be defined by the user in their config file
1111
# If there is a name collision, the default imports will be given priority
1212
# while the user defined functions are renamed with an underscore.
13-
#
13+
#
1414
# For example, if the user were to define their own function named `list` (the same name as a default below),
1515
# the user defined `list` will be renamed to `_list`.
1616
DEFAULTS = {
@@ -49,7 +49,7 @@ def __init__(self, yaml_path, config):
4949

5050
with open(yaml_path, 'r') as f:
5151
self.yaml = yaml.load(f, Loader=yaml.Loader)
52-
52+
5353
func_yaml = self.yaml.get('functions',{})
5454
filter_yaml = self.yaml.get('filters', {})
5555
self._funcs = self._import_function_dict(func_yaml)
@@ -58,7 +58,7 @@ def __init__(self, yaml_path, config):
5858
# Loops through each item in the config, passes
5959
# the data off to _import_function which will return
6060
# the actual function if it exists, and then adds
61-
# each function to the function dictionary so they can
61+
# each function to the function dictionary so they can
6262
# be added by extended_macro to the Jinja environment
6363

6464
def GetFunctions(self):
@@ -112,19 +112,19 @@ def get_macro(self, macro_name):
112112
macro = self.printer.lookup_object('extended_macro %s' % (macro_name))
113113
except:
114114
macro = self.printer.lookup_object('gcode_macro %s' % (macro_name))
115-
115+
116116
else:
117117
macro = self.printer.lookup_object(macro_name)
118118

119119
return macro
120120

121121
# update_gcode_variable
122122
#
123-
# Set the value of any GCode Variable for another (or the current) macro.
123+
# Set the value of any GCode Variable for another (or the current) macro.
124124
#
125125
# Main differences between SET_GCODE_VARIABLE:
126126
# * Can only be called in a macro
127-
# * Can update any variable, not just literals.
127+
# * Can update any variable, not just literals.
128128
# * Does not require running through the interpreter; instead is only run inside Python
129129
#
130130
def update_gcode_variable(self, macro_name, variable, value):
@@ -144,7 +144,7 @@ def call_macro(self, macro_name, **params):
144144
kwparams['params'] = params
145145
macro.template.run_gcode_from_command(kwparams)
146146

147-
# update_dict
147+
# update_dict
148148
#
149149
# Allows for updating a nested dictionary by passing a list, set, or tuple of keys.
150150
# If the set of keys do not lead to a valid existing item, the keys will be created.
@@ -177,7 +177,7 @@ def __init__(self, config):
177177
self.printer = self.config.get_printer()
178178
self.gcode = self.printer.lookup_object('gcode')
179179
self.Log = Logger(config)
180-
180+
181181
self.config_path = config.get('path', None)
182182
self.Loader = self._get_loader()
183183
self.Functions = self._import_functions()
@@ -203,14 +203,14 @@ def _import_functions(self):
203203
else:
204204
u_key = key
205205
all_funcs[u_key] = val
206-
206+
207207
return all_funcs
208208

209209
def _get_loader(self, ext=None):
210210
loader = None
211211
if ext is None:
212212
ext = self.config_path.split('.')[-1]
213-
213+
214214
for l in LOADERS:
215215
c_ext = l['extensions']
216216

@@ -233,7 +233,7 @@ def _load_defaults(self):
233233
loader = self._get_loader('default')
234234
funcs = self._load_functions(loader)
235235
return funcs
236-
236+
237237
def _load_filters(self):
238238
return self.Loader.GetFilters()
239239

@@ -246,43 +246,43 @@ def _load_functions(self, loader=None):
246246
return funcs, defaults_loaded
247247

248248
def _insert_function(self, func_name, func):
249-
if func_name in self.Functions:
249+
if func_name in self.Functions:
250250
func_name = '_%s' % func_name
251251

252252
def load_config(config):
253253
return PythonFunction(config)
254254

255255
# LOADERS
256256
# The definitions in this list will be used to determine the proper loader for the extensions given
257-
#
258-
# Since different loaders might need or want different methods of parsing the file,
257+
#
258+
# Since different loaders might need or want different methods of parsing the file,
259259
# the script expects that the loader is a function, not a class. The function should
260260
# process the config file and return a dictionary with the jinja function name as the key
261261
# and the actual Python function as the value
262-
#
262+
#
263263
# The loader for DEFAULTS should be defined with an extension of ['default']
264264
# This loader will be ignored if the property loader.DefaultsLoaded property is true (see below)
265-
#
265+
#
266266
# Definition: {'extensions': <collection_or_string>, 'loader': <class>}
267-
#
268-
# Arguments received:
267+
#
268+
# Arguments received:
269269
# * config_path: Path to config set in [extended_template]
270270
# * config: Config object received from Klipper
271271
#
272272
# Required Properties and Functions:
273273
# * loader.DefaultsLoaded <property>: <bool>
274-
# - If True, it is assumed the loader has loaded the defaults listed below.
274+
# - If True, it is assumed the loader has loaded the defaults listed below.
275275
# - If False, assumes the loader has not loaded the defaults listed below.
276276
# - It is suggested that the Loader should never process defaults unless:
277277
# * The user defines the defaults in the config file
278278
# * The loader defines it's own defaults
279279
# * Any other scenario where it's better to load the defaults by the loader instead of separately
280-
# * loader.GetFunctions(self) <function> = <dict>
280+
# * loader.GetFunctions(self) <function> = <dict>
281281
# - Loads user-defined functions.
282-
# * Optionally,
282+
# * Optionally,
283283
# - Returns schema: {defined_function_name_for_jinja <str>: function <callable>}
284-
#
285-
#
284+
#
285+
#
286286
LOADERS = [
287287
{
288288
'extensions': ['yaml','yml'],

extended_macro/readme.md

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# extended_macro
1+
# Extended_Template
22
---
33
* Allow the use of custom Python functions in your Klipper macros by defining the functions in a YAML config file
44
* By default includes many additional modules and functions. See below for more information.
@@ -9,27 +9,24 @@
99

1010
**Do not blindly download Python scripts, both for use in your macros and this script itself.** Read the script and ensure you understand what is going on. The scripts can be powerful and useful, but they can also be dangerous. If the script looks questionable, dangerous, or too confusing, it's better to assume that it is malicious.
1111

12-
**Installation:**
13-
1. Write down the location of the following directories:
12+
**What will happen when you run the Installation script:**
13+
1. The script will determine if the following directories exist:
1414
* Klipper Extras: Usually located at `/home/USER/klipper/klippy/extras`.
1515
* Klippy Virtual Environment `bin` directory: Usually located at `/home/USER/klippy/bin`
16-
2. Clone this repository or download `extended_macro.py`, `extended_template.py`, and `requirements.txt`
17-
3. Move `extended_macro.py` and `extended_template.py` to your Klipper Extras folder.
18-
4. Move `requirements.txt` to your home directory.
19-
5. Run the following command, substituting `${KLIPPY_ENV}` with the Klippy Virtual Environment bin directory:
20-
21-
```
22-
${KLIPPY_ENV}/pip install -r ${HOME}/requirements.txt
23-
```
16+
2. It will clone this repository; the following files will be downloaded:
17+
`extended_macro.py`, `extended_template.py`, and `delayed_extended.py`
18+
3. The script will install additional software if this extension has not been installed before
19+
4. The script creates a symbolic link from the clone Repo to the Klipper Extras folder for the following files:
20+
`extended_macro.py`, `extended_template.py` and `delayed_extended.py`
21+
5. If Klipper needs to be restarted the script will cause a Klipper restart.
2422

2523
---
2624
**Setup:**
2725

2826
1. In your Klipper config, add the following section. Nothing more is needed if you do not plan on using your own Python scripts:
29-
```
27+
```INI
3028
[extended_template]
3129
```
32-
3330
---
3431
**Adding your own Python functions**
3532

@@ -42,14 +39,16 @@ ${KLIPPY_ENV}/pip install -r ${HOME}/requirements.txt
4239
---
4340
**Usage:**
4441

45-
See the examples folder for more guidance.
42+
See the examples' folder for more guidance.
43+
44+
When defining the macro, use `extended_macro` as the config name instead of `gcode_macro`. To use your function, you will wrap the name with curly brackets (`{gcode_function_name_goes_here}`).
4645

47-
When defining the macro, use `extended_macro` as the config name instead of `gcode_macro`. To use your function, you will wrap the name with curly brackets (`{gcode_function_name_goes_here}`).
46+
When you need the macro to be used on an timer instead of `extended_macro` use `delayed_extended` as the section definition.
4847

4948
---
5049
**Defaults**
5150

52-
`extended_macro` comes with many default functions which do not need to be added or declared by the user.
51+
`extended_macro` and `delayed_extended` comes with many default functions which do not need to be added or declared by the user.
5352

5453
---
5554

@@ -60,46 +59,43 @@ On your Run the following commands in the command prompt of the Raspberry Pi run
6059

6160
```BASH
6261
cd ~
63-
git clone https://github.com/droans/klipper_extras.git
62+
git clone -b shell-install --single-branch git@github.com:droans/klipper_extras.git
6463
```
6564

66-
Next, install Extended Macro using our install script. As with any script, please take time and read the script first so you can ensure the safety. Alternatively, if you understand how, you may download the files and manually install Extended Macro:
65+
Next, install Extended Template using our installation script. As with any script, please take time and read the script first, so you can ensure the safety. Alternatively, if you understand how, you may download the files and manually install Extended Macro:
6766

6867
```BASH
6968
./klipper_extras/install.sh
7069
```
7170

72-
When the script finishes, copy the install script to your home directory so that we can edit it. On Line #3, you will need to adjust `FLAG=1` to `FLAG=0`. The reason for copying the file to your home directory is Moonraker will not like it if you edit the file while it is in the clone repo directory and will force you to overwrite the changes.
73-
74-
```BASH
75-
cp ${HOME}/klipper_extras/install.sh ${HOME}/extended_macro_install.sh
76-
nano /home/pi/extended_macro_install.sh
77-
```
78-
7971
At this point, Extended Macro is ready to be used. If you wish to add this to your update manager, edit your `moonraker.conf` file and add the following:
8072

81-
```BASH
82-
[update_manager extended_macro]
73+
```INI
74+
[update_manager extended_template]
8375
type: git_repo
84-
primary_branch: main
76+
primary_branch: shell-install
8577
path: ~/klipper_extras
8678
origin: https://github.com/droans/klipper_extras.git
8779
env: ~/klippy-env/bin/python
8880
requirements: extended_macro/requirements.txt
89-
install_script: ./../extended_macro_install.sh
81+
install_script: install.sh
9082
is_system_service: False
9183
managed_services: klipper
9284
```
9385

94-
With this above setup pointing the installation script to your home directory, anytime the extended_macro extension gets updated, your extended_macro_install.sh file will not be overwritten by the GitHub clone of the repo.
86+
The script will automatically generate the `requirements.txt` file and (if the use chooses to have moonraker update this extension automatically) `extended_template_update.conf` file.
9587

96-
We want the `FLAG=0` to stay that way. You only need to install the additional software packages one time. Moonraker will take care of ensuring that the packages needed by the extension are updated (the `requirements` option takes care of that for you).
88+
If the user chooses to have moonraker update this extension automatically, then the script will append the following to the end of your `moonraker.conf` file:
9789

90+
```INI
91+
#add extended_template extension to Klipper
92+
[include extended_template_update.conf]
93+
```
9894
---
9995

10096
*Custom Utility Functions*:
10197

102-
`update_gcode_variable(macro_name: str, variable: str, value: Any)`: Update a G-Code variable for any macro. Unlike `SET_GCODE_VARIABLE`, allows for non-literals to be passed and updated.
98+
`update_gcode_variable(macro_name: str, variable: str, value: Any)`: Update a G-Code variable for any macro. Unlike `SET_GCODE_VARIABLE`, allows for non-literals to be passed and updated.
10399

104100
`update_dict(dict: dict, keys: Union[list, tuple, set, str], value: Any)`: Update the value of a dictionary. Allows for a nested value to be updated if a list, tuple, or set is passed for `keys`.
105101

extended_macro/requirements.txt

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)