* Not necessarily valid for every meaning of the word "Everything"
Or: how do I get rid of all those red squigglies?
In CMakeCache.txt
set WITH_PYTHON_MODULE:BOOL=ON
make && make install
Install them, well documented how
mkvirtualenv -p /usr/bin/python3.5 bladdons
cdvirtualenv
cd lib/python3.5/site-packages
ln -s ~/workspace/blender-git/build_bpy/bin/bpy.so
ln -s ~/workspace/blender-git/blender/release
% python
Python 3.5.2 (default, Sep 10 2016, 08:21:44)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import bpy
>>> bpy.ops.wm.quit_blender()
Blender quit
Where you want them to be
Blender Text Editor has many examples
import bpy
def main(context):
for ob in context.scene.objects:
print(ob)
class SimpleOperator(bpy.types.Operator):
"""Tooltip"""
bl_idname = "object.simple_operator"
bl_label = "Simple Object Operator"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
main(context)
return {'FINISHED'}
def register():
bpy.utils.register_class(SimpleOperator)
def unregister():
bpy.utils.unregister_class(SimpleOperator)
bl_info = {
'name': 'Blender Cloud',
'author': 'Sybren A. Stüvel, Francesco Siddi, Inês Almeida, Antony Riakiotakis',
'version': (1, 4, 99),
'blender': (2, 77, 0),
'location': 'Addon Preferences panel, and Ctrl+Shift+Alt+A anywhere for texture browser',
'description': 'Texture library browser and Blender Sync. Requires the Blender ID addon '
'and Blender 2.77a or newer.',
'wiki_url': 'http://wiki.blender.org/index.php/Extensions:2.6/Py/'
'Scripts/System/BlenderCloud',
'category': 'System',
'warning': 'This is a beta version; the first to support Attract.'
}
Parsed, not executed
bpy.ops.bcloud.browse
class BCLOUD_OT_browse
bl_idname='mesh.scramble'
... and similar for menus, headers, etc.
unregister()
register()
# Your code
x = 5
# Your new code
x = 8
if "bpy" in locals():
import importlib
importlib.reload(Boltfactory)
else:
from add_mesh_BoltFactory import Boltfactory
import bpy
...
self.report()
print()
statementslogging
moduleprint()
statementssudo apt-get install eclipse-pydev
/home/sybren/.p2/pool/plugins/org.python.pydev_5.3.0.201610121612/pysrc/pydevd.py
print()
class SimpleOperator(bpy.types.Operator):
bl_idname = "object.simple_operator"
bl_label = "Simple Object Operator"
log = logging.getLogger('bpy.ops.%s' % bl_idname)
def execute(self, context):
self.log.info('It is happening now in scene %s', context.scene)
if not context.object:
self.log.warning('No active object, not doing anything')
self.log.debug('Not doing anything here either')
return {'FINISHED'}
Shown on stdout
, only WARNING or higher level.
No active object, not doing anything
Still shown on stdout
, INFO or higher level.
DEBUG level for selected loggers.
Metadata shown partially.
16:00:03.03 bpy.ops.object.simple_operator WARNING No active object, not doing anything
16:00:03.13 bpy.ops.object.simple_operator DEBUG Not doing anything here either
Loaded at Blender startup.
.../scripts/startup/config_logging.py
~/.config/blender/2.78/...
%APPDATA%\Blender Foundation\Blender\2.78\...
/Users/$USER/Library/Application Support/Blender/2.78/...
import logging.config
logging.config.dictConfig({
'version': 1,
'formatters': {'default': {'format': '%(asctime)-15s %(levelname)8s %(name)s %(message)s'}},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'default',
'stream': 'ext://sys.stderr',
}
},
'loggers': {
'bpy.ops.': {'level': 'DEBUG'},
'blenderid': {'level': 'DEBUG'},
'bid_api': {'level': 'DEBUG'},
'bid_addon_support': {'level': 'DEBUG'},
},
'root': {
'level': 'WARNING',
'handlers': ['console'],
}
})
The what & how should be clear from code.
Docstring can describe the what, and is the first thing to write.
Warning: There is a known bug with using a callback, Python must keep a reference to the strings returned or Blender will misbehave or even crash.
def pyside_cache(wrapped):
"""Stores the result of the callable in Python-managed memory.
This is to work around the warning at
https://www.blender.org/api/blender_python_api_master/bpy.props.html#bpy.props.EnumProperty
"""
import functools
@functools.wraps(wrapped)
# We can't use (*args, **kwargs), because EnumProperty explicitly checks
# for the number of fixed positional arguments.
def wrapper(self, context):
result = None
try:
result = wrapped(self, context)
return result
finally:
wrapped._cached_result = result
return wrapper
This stores the cached results in the bl_rna
dict for the property, rather
than on the callback function. A downside is that the decorator now needs the name of
the property it's a callback for.
def pyside_cache(propname):
if callable(propname):
raise TypeError('Usage: pyside_cache("property_name")')
def decorator(wrapped):
"""Stores the result of the callable in Python-managed memory.
This is to work around the warning at
https://www.blender.org/api/blender_python_api_master/bpy.props.html#bpy.props.EnumProperty
"""
import functools
@functools.wraps(wrapped)
# We can't use (*args, **kwargs), because EnumProperty explicitly checks
# for the number of fixed positional arguments.
def wrapper(self, context):
result = None
try:
result = wrapped(self, context)
return result
finally:
rna_type, rna_info = getattr(self.bl_rna, propname)
rna_info['_cached_result'] = result
return wrapper
return decorator
"A function should have only one point of return"
... and use break
, continue
etc.
def some_func(param1: int, param2: float) -> float:
"""Performs our special snowflake multiplication.
:param param1: non-zero integer
:param param2: positive float
:returns: our magic number
"""
if param1 != 0:
if param2 > 0:
return param1 * param2
else:
raise ValueError('param2 must be positive')
else:
raise ValueError('param1 may not be zero')
def some_func(param1: int, param2: float) -> float:
"""Performs our special snowflake multiplication.
:param param1: non-zero integer
:param param2: positive float
:returns: our magic number
"""
if param1 == 0:
raise ValueError('param1 may not be zero')
if param2 <= 0:
raise ValueError('param2 must be positive')
return param1 * param2
def somefunc(...):
...
if jemoeder.weight > 3:
return True
else:
return False
def somefunc(...):
...
return jemoeder.weight > 3
bpy.utils.user_resource('CACHE')
(once T47684 is done)
https://github.com/ActiveState/appdirs/blob/master/appdirs.py
is not the same as