1 2#A* ------------------------------------------------------------------- 3#B* This file contains source code for the PyMOL computer program 4#C* Copyright (c) Schrodinger, LLC. 5#D* ------------------------------------------------------------------- 6#E* It is unlawful to modify or remove this copyright notice. 7#F* ------------------------------------------------------------------- 8#G* Please see the accompanying LICENSE file for further information. 9#H* ------------------------------------------------------------------- 10#I* Additional authors of this source file include: 11#-* 12#-* 13#-* 14#Z* ------------------------------------------------------------------- 15 16# cmd.py 17# Python interface module for PyMol 18# 19# **This is the only module which should be/need be imported by 20# ** PyMol API Based Programs 21 22# NEW CALL RETURN CONVENTIONS for _cmd.so C-layer 23# 24 25# (1) Calls into C (_cmd) should return results/status and print 26# errors and feedback (according to mask) BUT NEVER RAISE EXCEPTIONS 27# from within the C code itself. 28 29# (2) Effective with version 0.99, standard Python return conventions 30# apply, but haven't yet been fully implemented. In summary: 31 32# Unless explicitly specified in the function: 33 34# ==> Success with no information should return None 35 36# ==> Failure should return a negative number as follows: 37# -1 = a general, unspecified failure 38 39# Upon an error, exceptions will be raised by the Python wrapper 40# layer if the "raise_exceptions" setting is on. 41 42# ==> Boolean queries should return 1 for true/yes and 0 for false/no. 43 44# ==> Count queries should return 0 or a positive number 45 46# (3) If _cmd produces a specific return result, be sure to include an 47# error result as one of the possibilities outside the range of the 48# expected return value. For example, a negative distance 49# 50# (4) cmd.py API wrappers can then raise exceptions and return values. 51# 52# NOTE: Output tweaking via the "quiet" parameter of API functions. 53# 54# Many PyMOL API functions have a "quiet" parameter which is used to 55# customize output depending on when and where the routine was called. 56# 57# As defined, quiet should be 1. Called from an external module, output 58# to the console should be minimal. 59# 60# However, when a command is run through the parser (often manually) the 61# user expects a little more feedback. The parser will automatically 62# set "quiet" to zero 63# 64# In rare cases, certain nonserious error or warning output should 65# also be suppressed. Set "quiet" to 2 for this behavior. 66 67from __future__ import print_function 68 69def _deferred_init_pymol_internals(_pymol): 70 # set up some global session tasks 71 72 if viewing.session_restore_views not in _pymol._session_restore_tasks: 73 _pymol._session_restore_tasks.append(viewing.session_restore_views) 74 75 if viewing.session_save_views not in _pymol._session_save_tasks: 76 _pymol._session_save_tasks.append(viewing.session_save_views) 77 78 if viewing.session_restore_scenes not in _pymol._session_restore_tasks: 79 _pymol._session_restore_tasks.append(viewing.session_restore_scenes) 80 81 if wizarding.session_restore_wizard not in _pymol._session_restore_tasks: 82 _pymol._session_restore_tasks.append(wizarding.session_restore_wizard) 83 84 if wizarding.session_save_wizard not in _pymol._session_save_tasks: 85 _pymol._session_save_tasks.append(wizarding.session_save_wizard) 86 87 # take care of some deferred initialization 88 89 _pymol._view_dict_sc = Shortcut({}) 90 _pymol._scene_dict_sc = Shortcut({}) 91 92 # 93if True: 94 95 import sys 96 97 # pymol2.cmd2 exposes a weak reference, this is not possible (and not 98 # necessary) on the module level, so we simply make a self reference. 99 _weakrefproxy = sys.modules[__name__] 100 101 if True: 102 103 import re 104 from pymol import _cmd 105 import string 106 import threading 107 import pymol 108 import os 109 from . import parsing 110 import time 111 112 _pymol = pymol 113 114 from .shortcut import Shortcut 115 116 from chempy import io 117 118 ####################################################################### 119 # symbols for early export 120 ####################################################################### 121 122 from .constants import * 123 from .constants import _load2str 124 125 fb_debug = sys.stderr # can redirect python debugging output elsewhere if desred... 126 127 #-------------------------------------------------------------------- 128 # convenient type and result checking 129 130 from .checking import * 131 from .checking import _raising 132 133 #------------------------------------------------------------------- 134 # path expansion, including our fixes for Win32 135 136 def _nt_expandvars(path): # allow for //share/folder$/file 137 path = nt_hidden_path_re.sub(r"$$\\",path) 138 return os.path.expandvars(path) 139 140 if "nt" in sys.builtin_module_names: 141 _expandvars = _nt_expandvars 142 else: 143 _expandvars = os.path.expandvars 144 145 def exp_path(path): 146 path = as_pathstr(path) 147 return _expandvars(os.path.expanduser(path)) 148 149 def as_pathstr(path): 150 # On Windows, always work with unicode file names. On Unix, 151 # UTF-8 byte strings seem to be fine, so keep them for now. 152 if isinstance(path, bytes) and pymol.IS_WINDOWS: 153 for encoding in ('utf-8', 'mbcs'): 154 try: 155 return path.decode(encoding) 156 except UnicodeError: 157 pass 158 return path 159 160 #-------------------------------------------------------------------- 161 # locks and threading 162 163 reaper = None 164 165 # the following locks are used by both C and Python to insure that no more than 166 # one active thread enters PyMOL at a given time. 167 168 lock_api = pymol.lock_api 169 lock_api_status = pymol.lock_api_status 170 lock_api_glut = pymol.lock_api_glut 171 lock_api_data = pymol.lock_api_data 172 lock_api_allow_flush = 1 173 174 from .locking import * 175 lockcm = LockCM() 176 177 #-------------------------------------------------------------------- 178 # status monitoring 179 180 from .monitoring import * 181 182 #-------------------------------------------------------------------- 183 # Feedback 184 185 from .feedingback import * 186 from .feedingback import _feedback 187 188 #-------------------------------------------------------------------- 189 # internal API routines 190 191 from . import internal 192 193 _alt = internal._alt 194 _coordset_update_spawn = internal._coordset_update_spawn 195 _coordset_update_thread = internal._coordset_update_thread 196 _copy_image = internal._copy_image 197 _ctrl = internal._ctrl 198 _ctsh = internal._ctsh 199 _do = internal._do 200 _dump_floats = internal._dump_floats 201 _dump_ufloats = internal._dump_ufloats 202 _fake_drag = internal._fake_drag 203 _get_color_sc = internal._get_color_sc 204 _get_feedback = internal._get_feedback 205 _interpret_color = internal._interpret_color 206 _invalidate_color_sc = internal._invalidate_color_sc 207 _mpng = internal._mpng 208 _object_update_spawn = internal._object_update_spawn 209 _object_update_thread = internal._object_update_thread 210 _png = internal._png 211 _quit = internal._quit 212 _ray_anti_spawn = internal._ray_anti_spawn 213 _ray_hash_spawn = internal._ray_hash_spawn 214 _ray_spawn = internal._ray_spawn 215 _refresh = internal._refresh 216 _special = internal._special 217 _validate_color_sc = internal._validate_color_sc 218 _cache_get = internal._cache_get 219 _cache_set = internal._cache_set 220 _cache_clear = internal._cache_clear 221 _cache_purge = internal._cache_purge 222 _cache_mark = internal._cache_mark 223 _sdof = internal._sdof 224 225 ####################################################################### 226 # now import modules which depend on the above 227 ####################################################################### 228 229 from . import editor 230 231 ####################################################################### 232 # cmd module functions... 233 ####################################################################### 234 235 # for extending the language 236 237 from .commanding import extend, extendaa, alias 238 239 # for documentation etc 240 241 from .helping import python_help 242 243 def write_html_ref(file): 244 '''Write the PyMOL Command Reference to an HTML file''' 245 f=open(file,'w') 246 kees = [a for a in keywords.get_command_keywords() 247 if not a.startswith('_') and keyword[a][0] != python_help] 248 kees.sort() 249 title = 'PyMOL Command Reference' 250 f.write('''<html> 251<head> 252<title>%s</title> 253<style type='text/css'> 254body, p, h1, h2 { 255 font-family: sans-serif; 256} 257p.api { 258 font:small monospace; 259 color:#999; 260} 261pre.example { 262 background-color: #ccc; 263 padding: 5px; 264} 265li { 266 display: block; 267 width: 10em; 268 float: left; 269} 270</style> 271</head> 272<body> 273<h1>%s</h1> 274 275<p>This is the list of all PyMOL commands which can be used in the PyMOL 276command line and in PML scripts. The command descriptions found in this 277file can also be printed to the PyMOL text buffer with the 278<a href="#help">help</a> command. Example:</p> 279 280<pre class="example">PyMOL>help color 281...</pre> 282 283<p>The list of arguments for a command (the "usage") can be queried on 284the command line with a questionmark. Example:</p> 285 286<pre class="example">PyMOL>color ? 287Usage: color color [, selection [, quiet [, flags ]]]</pre> 288 289<p>The square brackets ("[" and "]") indicate optional arguments and are 290not part of the syntax.</p> 291 292<p>If the PyMOL command interpreter doesn't understand some input, it passes 293it to the Python interpreter. This means that single-line Python expressions 294can be put into PML scripts or typed into the command line. Prefixing a line 295with a slash (/) forces the interpreter to pass it to Python. See also the 296<a href="#python">python</a> command to input multi-line Python scripts.</p> 297 298<p>This file can be generated on the PyMOL command line:</p> 299<pre class="example">PyMOL>cmd.write_html_ref('pymol-command-ref.html')</pre> 300 301<hr size=1> 302 303<ul> 304''' % (title, title)) 305 306 for a in kees: 307 f.write("<li><a href='#%s'>%s</a></li>" % (a, a)) 308 309 f.write('</ul><br style="clear: both">') 310 311 def make_see_also_link(m): 312 w = m.group() 313 if w in kees: 314 return "<a href='#%s'>%s</a>" % (w, w) 315 return w 316 317 for a in kees: 318 func = keyword[a][0] 319 doc = (getattr(func, '__doc__') or 'UNDOCUMENTED').strip(). \ 320 replace("<", "<"). \ 321 replace(">", ">").splitlines() 322 323 # attemt to do some HTML formatting 324 isseealso = False 325 for i, line in enumerate(doc): 326 if not line.strip(): 327 continue 328 isindented = line[:1].isspace() 329 if isindented: 330 if isseealso: 331 doc[i] = re.sub(r'\w+', make_see_also_link, line) 332 elif line.isupper(): 333 isseealso = line.startswith('SEE ALSO') 334 doc[i] = '<b>' + line + '</b>' 335 336 f.write("<hr size=1><h2 id='%s'>%s</h2>" % (a, a)) 337 f.write("<pre>%s</pre>" % ('\n'.join(doc))) 338 f.write("<p class='api'>api: %s.%s</p>" % (func.__module__, func.__name__)) 339 f.write("</BODY></HTML>") 340 f.close() 341 342 print("PyMOL Command Reference written to %s" % (os.path.abspath(file))) 343 344 345 ##################################################################### 346 # Here is where the PyMOL Command Language and API are built. 347 ##################################################################### 348 349 # first we need to import a set of symbols into the local namespace 350 351 from .api import * 352 353 # deferred initialization 354 355 _deferred_init_pymol_internals(pymol) 356 357 # now we create the command langauge 358 359 from . import keywords 360 keyword = keywords.get_command_keywords() 361 kw_list = list(keyword.keys()) 362 363 keywords.fix_list(kw_list) 364 kwhash = Shortcut(kw_list) 365 keywords.fix_dict(keyword) 366 367 # informational or API-only functions which don't exist in the 368 # PyMOL command language namespace 369 370 help_only = keywords.get_help_only_keywords() 371 help_sc = Shortcut(list(keyword.keys())+list(help_only.keys())) 372 373 # keyboard configuration 374 375 from . import keyboard 376 377 key_mappings = keyboard.get_default_keys() 378 379 selection_sc = lambda sc=Shortcut,gn=get_names:sc(gn('public')+[ 380 'not ', 'and ', 'or ', 'first ', 'last ', 'in ', 'like ', 381 382 'byobject ', 'bysegi ', 'bychain ', 'byres ', 'bycalpha ', 383 'bymolecule ', 384 385 'bound_to ', 'neighbor ', 'extend ', 'within ', 'around ', 386 'expand ', 'gap ', 'near_to ', 'beyond ', 387 388 'model ', 'chain ', 'segi ', 'resn ', 'resi ', 'name ', 'alt ', 'index ', 389 'id ', 'rank ', 390 391 'partial_charge ', 'formal_charge ', 'b ', 'q ', 'ss ', 'elem ', 392 'rep ', 'color ', 'pepseq ', 393 394 'all', 'enabled', 'visible', 'bonded', 'protected', 'masked', 395 'organic', 'inorganic', 'solvent', 'polymer', 'guide', 'hetatm', 396 'hydrogens', 'backbone', 'sidechain', 'metals', 'donors', 397 'acceptors', 398 'polymer.protein', 'polymer.nucleic', 399 400 'center', 'origin', 401 ]) 402 403 object_sc = lambda sc=Shortcut,gn=get_names:sc(gn('objects')) 404 map_sc = lambda sc=Shortcut,gnot=get_names_of_type:sc(gnot('object:map')) 405 contour_sc = lambda sc=Shortcut,gnot=get_names_of_type:sc(gnot('object:mesh')+gnot('object:surface')) 406 group_sc = lambda sc=Shortcut,gnot=get_names_of_type:sc(gnot('object:group')) 407 408 # Table for argument autocompletion 409 410 from . import completing 411 412 auto_arg = completing.get_auto_arg_list() 413 414 color_sc = None 415 416 raw_image_callback = None 417