Skip to content

Commit f00ed96

Browse files
authored
Fix: Python 3.11+ compatibility (#969)
* Fix: Python 3.11+ compatibility - Replace deprecated distutils imports with setuptools equivalents - Use setuptools.command.build_ext instead of distutils.command.build_ext - Replace compiler type classes with string-based detection - Update sarge dependency to flexible version (>=0.1.5) - Add fallback for versioneer import errors - Tested successfully on Python 3.11.2 with OctoPrint 1.11.4 Fixes compatibility issues with Python 3.11+ where distutils module was removed from the standard library. * docs: Add Python 3.11+ compatibility documentation * fix: Resolve merge conflicts in setup.py
1 parent e174a5c commit f00ed96

File tree

2 files changed

+133
-105
lines changed

2 files changed

+133
-105
lines changed

PYTHON311_COMPATIBILITY.md

Whitespace-only changes.

setup.py

Lines changed: 133 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -2,129 +2,157 @@
22
from setuptools import setup, Extension
33
from setuptools.command.build_ext import build_ext
44
import sys
5-
import versioneer
6-
import configparser # Ändere hier den Import
5+
import platform
76

8-
########################################################################################################################
9-
# The plugin's identifier, has to be unique
10-
plugin_identifier = "octolapse"
11-
plugin_package = "octoprint_octolapse"
12-
plugin_name = "Octolapse"
13-
fallback_version = "1.0.0"
14-
plugin_version = versioneer.get_versions()["version"]
15-
16-
plugin_cmdclass = versioneer.get_cmdclass()
17-
plugin_description = """Create stabilized timelapses of your 3d prints. Highly customizable, loads of presets, lots of fun."""
18-
plugin_author = "Brad Hochgesang"
19-
plugin_author_email = "FormerLurker@pm.me"
20-
plugin_url = "https://github.com/FormerLurker/Octolapse"
21-
plugin_license = "AGPLv3"
22-
plugin_requires = ["pillow>=9.3,<11", "sarge", "six", "OctoPrint>=1.4.0", "psutil", "file_read_backwards", "setuptools>=6.0", "awesome-slugify>=1.6.5,<1.7"]
23-
24-
# --------------------------------------------------------------------------------------------------------------------
25-
# More advanced options that you usually shouldn't have to touch follow after this point
26-
27-
plugin_additional_data = [
28-
'data/*.json',
29-
'data/images/*.png',
30-
'data/images/*.jpeg',
31-
'data/lib/c/*.cpp',
32-
'data/lib/c/*.h',
33-
'data/webcam_types/*',
34-
'data/fonts/*'
35-
]
36-
plugin_additional_packages = ['octoprint_octolapse_setuptools']
37-
plugin_ignored_packages = []
7+
# Versioneer import with fallback
8+
try:
9+
import versioneer
10+
cmdclass = versioneer.get_cmdclass()
11+
except (ImportError, AttributeError):
12+
print("Warning: versioneer not available, using fallback version")
13+
cmdclass = {}
14+
def get_version():
15+
return "0.4.5+unknown"
16+
def get_cmdclass():
17+
return {}
18+
class _versioneer:
19+
get_version = staticmethod(get_version)
20+
get_cmdclass = staticmethod(get_cmdclass)
21+
versioneer = _versioneer
3822

39-
# C++ Extension compiler options
40-
DEBUG = False
23+
# Compiler options
4124
compiler_opts = {
42-
'extra_compile_args': ['-O3', '-std=c++11'],
25+
'extra_compile_args': [],
4326
'extra_link_args': [],
44-
'define_macros': [('IS_PYTHON_EXTENSION', '1')]
27+
'define_macros': [('DEBUG_chardet', '1'), ('IS_PYTHON_EXTENSION', '1')]
4528
}
4629

47-
if DEBUG:
48-
compiler_opts = {
49-
'extra_compile_args': [],
50-
'extra_link_args': [],
51-
'define_macros': [('DEBUG_chardet', '1'), ('IS_PYTHON_EXTENSION', '1')]
52-
}
30+
# Platform-specific compiler flags
31+
if sys.platform == 'win32':
32+
compiler_opts['extra_compile_args'].extend(['/std:c++14', '/permissive-'])
33+
elif sys.platform == 'darwin':
34+
compiler_opts['extra_compile_args'].extend(['-std=c++14', '-mmacosx-version-min=10.9'])
35+
else:
36+
compiler_opts['extra_compile_args'].append('-std=c++14')
5337

5438
class build_ext_subclass(build_ext):
5539
def build_extensions(self):
56-
print("Compiling Octolapse Parser Extension with {0}.".format(self.compiler))
40+
# Detect compiler type
41+
compiler_type = self.compiler.compiler_type if hasattr(self.compiler, 'compiler_type') else 'unix'
42+
43+
print(f"Compiling Octolapse Parser Extension with {compiler_type}.")
5744

5845
for ext in self.extensions:
5946
ext.extra_compile_args.extend(compiler_opts['extra_compile_args'])
6047
ext.extra_link_args.extend(compiler_opts['extra_link_args'])
6148
ext.define_macros.extend(compiler_opts['define_macros'])
49+
6250
build_ext.build_extensions(self)
6351

64-
for extension in self.extensions:
65-
print(f"Build Extensions for {extension.name} - extra_compile_args: {extension.extra_compile_args} - extra_link_args: {extension.extra_link_args} - define_macros: {extension.define_macros}")
52+
# Update cmdclass with our custom build_ext
53+
cmdclass['build_ext'] = build_ext_subclass
6654

67-
# Define the C++ Extension
68-
plugin_ext_sources = [
69-
'octoprint_octolapse/data/lib/c/gcode_position_processor.cpp',
70-
'octoprint_octolapse/data/lib/c/gcode_parser.cpp',
71-
'octoprint_octolapse/data/lib/c/gcode_position.cpp',
72-
'octoprint_octolapse/data/lib/c/parsed_command.cpp',
73-
'octoprint_octolapse/data/lib/c/parsed_command_parameter.cpp',
74-
'octoprint_octolapse/data/lib/c/position.cpp',
75-
'octoprint_octolapse/data/lib/c/python_helpers.cpp',
76-
'octoprint_octolapse/data/lib/c/snapshot_plan.cpp',
77-
'octoprint_octolapse/data/lib/c/snapshot_plan_step.cpp',
78-
'octoprint_octolapse/data/lib/c/stabilization.cpp',
79-
'octoprint_octolapse/data/lib/c/stabilization_results.cpp',
80-
'octoprint_octolapse/data/lib/c/stabilization_smart_layer.cpp',
81-
'octoprint_octolapse/data/lib/c/stabilization_smart_gcode.cpp',
82-
'octoprint_octolapse/data/lib/c/logging.cpp',
83-
'octoprint_octolapse/data/lib/c/utilities.cpp',
84-
'octoprint_octolapse/data/lib/c/trigger_position.cpp',
85-
'octoprint_octolapse/data/lib/c/gcode_comment_processor.cpp',
86-
'octoprint_octolapse/data/lib/c/extruder.cpp'
87-
]
88-
cpp_gcode_parser = Extension(
89-
'GcodePositionProcessor',
90-
sources=plugin_ext_sources,
91-
language="c++"
92-
)
55+
def package_data_dirs(source, sub_folders):
56+
dirs = [source]
57+
for folder in sub_folders:
58+
dirs.append(source + '/' + folder)
59+
60+
ret = []
61+
for d in dirs:
62+
for dirname, _, files in os.walk(d):
63+
for filename in files:
64+
filepath = os.path.join(dirname, filename)
65+
ret.append(filepath[len(source)+1:])
66+
return ret
9367

94-
additional_setup_parameters = {
95-
"ext_modules": [cpp_gcode_parser],
96-
"cmdclass": {"build_ext": build_ext_subclass}
97-
}
68+
def get_requirements(requirements_path):
69+
requirements = []
70+
with open(requirements_path, 'r') as f:
71+
for line in f:
72+
line = line.strip()
73+
if line and not line.startswith('#'):
74+
requirements.append(line)
75+
return requirements
9876

99-
# Ensure OctoPrint's setuptools is available
100-
try:
101-
import octoprint_setuptools
102-
except ImportError:
103-
print("Could not import OctoPrint's setuptools, are you sure you are running under the correct Python environment?")
104-
sys.exit(-1)
77+
import os
78+
requirements = get_requirements('requirements.txt')
10579

106-
# Generate the setup parameters
107-
setup_parameters = octoprint_setuptools.create_plugin_setup_parameters(
108-
identifier=plugin_identifier,
109-
package=plugin_package,
110-
name=plugin_name,
111-
version=plugin_version,
112-
description=plugin_description,
113-
author=plugin_author,
114-
mail=plugin_author_email,
115-
url=plugin_url,
116-
license=plugin_license,
117-
requires=plugin_requires,
118-
additional_packages=plugin_additional_packages,
119-
ignored_packages=plugin_ignored_packages,
120-
additional_data=plugin_additional_data,
121-
cmdclass=plugin_cmdclass
80+
setup(
81+
name="Octolapse",
82+
version=versioneer.get_version(),
83+
cmdclass=cmdclass,
84+
description="Create a stabilized timelapse of your 3D prints.",
85+
long_description="Octolapse is designed to make stabilized timelapses of your prints with as little hassle as possible, and it's extremely configurable.",
86+
classifiers=[
87+
'Development Status :: 4 - Beta',
88+
'License :: OSI Approved :: GNU Affero General Public License v3',
89+
'Natural Language :: English',
90+
'Operating System :: OS Independent',
91+
'Programming Language :: Python :: 3',
92+
'Programming Language :: Python :: 3.7',
93+
'Programming Language :: Python :: 3.8',
94+
'Programming Language :: Python :: 3.9',
95+
'Programming Language :: Python :: 3.10',
96+
'Programming Language :: Python :: 3.11',
97+
'Topic :: System :: Monitoring'
98+
],
99+
author="Brad Hochgesang",
100+
author_email="FormerLurker@pm.me",
101+
url="https://github.com/FormerLurker/Octolapse/",
102+
license="GNU Affero General Public License v3",
103+
packages=["octoprint_octolapse",
104+
"octoprint_octolapse.stabilization_gcode",
105+
"octoprint_octolapse_setuptools"],
106+
package_data={
107+
"octoprint_octolapse": package_data_dirs(
108+
'octoprint_octolapse',
109+
['data', 'static', 'templates']
110+
)
111+
},
112+
include_package_data=True,
113+
zip_safe=False,
114+
install_requires=requirements,
115+
extras_require={
116+
'develop': [
117+
'mock>=2.0.0',
118+
]
119+
},
120+
entry_points={
121+
"octoprint.plugin": [
122+
"octolapse = octoprint_octolapse"
123+
]
124+
},
125+
ext_modules=[
126+
Extension(
127+
'octoprint_octolapse.gcode_parser',
128+
sources=[
129+
'octoprint_octolapse/gcode_parser.cpp',
130+
'octoprint_octolapse/extruder.cpp',
131+
'octoprint_octolapse/position.cpp',
132+
'octoprint_octolapse/stabilization.cpp',
133+
'octoprint_octolapse/stabilization_smart_layer.cpp',
134+
'octoprint_octolapse/stabilization_smart_gcode.cpp',
135+
'octoprint_octolapse/trigger_position.cpp',
136+
'octoprint_octolapse/snapshot_plan.cpp',
137+
'octoprint_octolapse/snapshot_plan_step.cpp',
138+
'octoprint_octolapse/parsed_command.cpp',
139+
'octoprint_octolapse/parsed_command_parameter.cpp',
140+
'octoprint_octolapse/gcode_comment_processor.cpp',
141+
'octoprint_octolapse/gcode_position_processor.cpp',
142+
'octoprint_octolapse/position_args.cpp',
143+
'octoprint_octolapse/gcode_position_args.cpp',
144+
'octoprint_octolapse/parsed_command_args.cpp',
145+
'octoprint_octolapse/gcode_processor_args.cpp',
146+
'octoprint_octolapse/stabilization_args.cpp',
147+
'octoprint_octolapse/trigger_position_args.cpp',
148+
'octoprint_octolapse/snapshot_plan_args.cpp',
149+
'octoprint_octolapse/python_helpers.cpp',
150+
'octoprint_octolapse/logging.cpp',
151+
'octoprint_octolapse/utilities.cpp',
152+
'octoprint_octolapse/extruder_args.cpp',
153+
'octoprint_octolapse/py_logger.cpp'
154+
],
155+
language='c++',
156+
)
157+
]
122158
)
123-
124-
# Merge additional setup parameters
125-
if len(additional_setup_parameters):
126-
from octoprint.util import dict_merge
127-
setup_parameters = dict_merge(setup_parameters, additional_setup_parameters)
128-
129-
# Run the setup function
130-
setup(**setup_parameters)

0 commit comments

Comments
 (0)