1# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- 2# 3# This file is part of the LibreOffice project. 4# 5# This Source Code Form is subject to the terms of the Mozilla Public 6# License, v. 2.0. If a copy of the MPL was not distributed with this 7# file, You can obtain one at http://mozilla.org/MPL/2.0/. 8# 9# This file incorporates work covered by the following license notice: 10# 11# Licensed to the Apache Software Foundation (ASF) under one or more 12# contributor license agreements. See the NOTICE file distributed 13# with this work for additional information regarding copyright 14# ownership. The ASF licenses this file to you under the Apache 15# License, Version 2.0 (the "License"); you may not use this file 16# except in compliance with the License. You may obtain a copy of 17# the License at http://www.apache.org/licenses/LICENSE-2.0 . 18# 19import pyuno 20import sys 21import traceback 22import warnings 23 24# since on Windows sal3.dll no longer calls WSAStartup 25import socket 26 27# All functions and variables starting with a underscore (_) must be 28# considered private and can be changed at any time. Don't use them. 29_component_context = pyuno.getComponentContext() 30 31 32def getComponentContext(): 33 """Returns the UNO component context used to initialize the Python runtime.""" 34 35 return _component_context 36 37 38def getCurrentContext(): 39 """Returns the current context. 40 41 See http://udk.openoffice.org/common/man/concept/uno_contexts.html#current_context 42 for an explanation on the current context concept. 43 """ 44 45 return pyuno.getCurrentContext() 46 47 48def setCurrentContext(newContext): 49 """Sets newContext as new UNO context. 50 51 The newContext must implement the XCurrentContext interface. The 52 implementation should handle the desired properties and delegate 53 unknown properties to the old context. Ensure that the old one 54 is reset when you leave your stack, see 55 http://udk.openoffice.org/common/man/concept/uno_contexts.html#current_context 56 """ 57 58 return pyuno.setCurrentContext(newContext) 59 60 61def getConstantByName(constant): 62 """Looks up the value of an IDL constant by giving its explicit name.""" 63 64 return pyuno.getConstantByName(constant) 65 66 67def getTypeByName(typeName): 68 """Returns a `uno.Type` instance of the type given by typeName. 69 70 If the type does not exist, a `com.sun.star.uno.RuntimeException` is raised. 71 """ 72 73 return pyuno.getTypeByName(typeName) 74 75 76def createUnoStruct(typeName, *args, **kwargs): 77 """Creates a UNO struct or exception given by typeName. 78 79 Can be called with: 80 81 1) No additional argument. 82 In this case, you get a default constructed UNO structure. 83 (e.g. `createUnoStruct("com.sun.star.uno.Exception")`) 84 2) Exactly one additional argument that is an instance of typeName. 85 In this case, a copy constructed instance of typeName is returned 86 (e.g. `createUnoStruct("com.sun.star.uno.Exception" , e)`) 87 3) As many additional arguments as the number of elements within typeName 88 (e.g. `createUnoStruct("com.sun.star.uno.Exception", "foo error" , self)`). 89 4) Keyword arguments to give values for each element of the struct by name. 90 5) A mix of 3) and 4), such that each struct element is given a value exactly once, 91 either by a positional argument or by a keyword argument. 92 93 The additional and/or keyword arguments must match the type of each struct element, 94 otherwise an exception is thrown. 95 """ 96 97 return getClass(typeName)(*args, **kwargs) 98 99 100def getClass(typeName): 101 """Returns the class of a concrete UNO exception, struct, or interface.""" 102 103 return pyuno.getClass(typeName) 104 105 106def isInterface(obj): 107 """Returns True, when obj is a class of a UNO interface.""" 108 109 return pyuno.isInterface(obj) 110 111 112def generateUuid(): 113 """Returns a 16 byte sequence containing a newly generated uuid or guid. 114 115 For more information, see rtl/uuid.h. 116 """ 117 118 return pyuno.generateUuid() 119 120 121def systemPathToFileUrl(systemPath): 122 """Returns a file URL for the given system path.""" 123 124 return pyuno.systemPathToFileUrl(systemPath) 125 126 127def fileUrlToSystemPath(url): 128 """Returns a system path. 129 130 This path is determined by the system that the Python interpreter is running on. 131 """ 132 133 return pyuno.fileUrlToSystemPath(url) 134 135 136def absolutize(path, relativeUrl): 137 """Returns an absolute file url from the given urls.""" 138 139 return pyuno.absolutize(path, relativeUrl) 140 141 142class Enum: 143 """Represents a UNO enum. 144 145 Use an instance of this class to explicitly pass an enum to UNO. 146 147 :param typeName: The name of the enum as a string. 148 :param value: The actual value of this enum as a string. 149 """ 150 151 def __init__(self, typeName, value): 152 self.typeName = typeName 153 self.value = value 154 pyuno.checkEnum(self) 155 156 def __repr__(self): 157 return "<Enum instance %s (%r)>" % (self.typeName, self.value) 158 159 def __eq__(self, that): 160 if not isinstance(that, Enum): 161 return False 162 163 return (self.typeName == that.typeName) and (self.value == that.value) 164 165 def __ne__(self,other): 166 return not self.__eq__(other) 167 168 169class Type: 170 """Represents a UNO type. 171 172 Use an instance of this class to explicitly pass a type to UNO. 173 174 :param typeName: Name of the UNO type 175 :param typeClass: Python Enum of TypeClass, see com/sun/star/uno/TypeClass.idl 176 """ 177 178 def __init__(self, typeName, typeClass): 179 self.typeName = typeName 180 self.typeClass = typeClass 181 pyuno.checkType(self) 182 183 def __repr__(self): 184 return "<Type instance %s (%r)>" % (self.typeName, self.typeClass) 185 186 def __eq__(self, that): 187 if not isinstance(that, Type): 188 return False 189 190 return self.typeClass == that.typeClass and self.typeName == that.typeName 191 192 def __ne__(self,other): 193 return not self.__eq__(other) 194 195 def __hash__(self): 196 return self.typeName.__hash__() 197 198 199class Bool(object): 200 """Represents a UNO boolean. 201 202 Use an instance of this class to explicitly pass a boolean to UNO. 203 204 Note: This class is deprecated. Use Python's True and False directly instead. 205 """ 206 207 def __new__(cls, value): 208 message = "The Bool class is deprecated. Use Python's True and False directly instead." 209 warnings.warn(message, DeprecationWarning) 210 211 if isinstance(value, str) and value == "true": 212 return True 213 214 if isinstance(value, str) and value == "false": 215 return False 216 217 if value: 218 return True 219 220 return False 221 222 223class Char: 224 """Represents a UNO char. 225 226 Use an instance of this class to explicitly pass a char to UNO. 227 228 For Python 3, this class only works with unicode (str) objects. Creating 229 a Char instance with a bytes object or comparing a Char instance 230 to a bytes object will raise an AssertionError. 231 232 :param value: A Unicode string with length 1 233 """ 234 235 def __init__(self, value): 236 assert isinstance(value, str), "Expected str object, got %s instead." % type(value) 237 238 assert len(value) == 1, "Char value must have length of 1." 239 assert ord(value[0]) <= 0xFFFF, "Char value must be UTF-16 code unit" 240 241 self.value = value 242 243 def __repr__(self): 244 return "<Char instance %s>" % (self.value,) 245 246 def __eq__(self, that): 247 if isinstance(that, str): 248 if len(that) > 1: 249 return False 250 251 return self.value == that[0] 252 253 if isinstance(that, Char): 254 return self.value == that.value 255 256 return False 257 258 def __ne__(self,other): 259 return not self.__eq__(other) 260 261 262class ByteSequence: 263 """Represents a UNO ByteSequence value. 264 265 Use an instance of this class to explicitly pass a byte sequence to UNO. 266 267 :param value: A string or bytesequence 268 """ 269 270 def __init__(self, value): 271 if isinstance(value, bytes): 272 self.value = value 273 274 elif isinstance(value, ByteSequence): 275 self.value = value.value 276 277 else: 278 raise TypeError("Expected bytes object or ByteSequence, got %s instead." % type(value)) 279 280 def __repr__(self): 281 return "<ByteSequence instance '%s'>" % (self.value,) 282 283 def __eq__(self, that): 284 if isinstance(that, bytes): 285 return self.value == that 286 287 if isinstance(that, ByteSequence): 288 return self.value == that.value 289 290 return False 291 292 def __len__(self): 293 return len(self.value) 294 295 def __getitem__(self, index): 296 return self.value[index] 297 298 def __iter__(self): 299 return self.value.__iter__() 300 301 def __add__(self, b): 302 if isinstance(b, bytes): 303 return ByteSequence(self.value + b) 304 305 elif isinstance(b, ByteSequence): 306 return ByteSequence(self.value + b.value) 307 308 else: 309 raise TypeError("Can't add ByteString and %s." % type(b)) 310 311 def __hash__(self): 312 return self.value.hash() 313 314 315class Any: 316 """Represents a UNO Any value. 317 318 Use only in connection with uno.invoke() to pass an explicit typed Any. 319 """ 320 321 def __init__(self, type, value): 322 if isinstance(type, Type): 323 self.type = type 324 else: 325 self.type = getTypeByName(type) 326 327 self.value = value 328 329 330def invoke(object, methodname, argTuple): 331 """Use this function to pass exactly typed Anys to the callee (using uno.Any).""" 332 333 return pyuno.invoke(object, methodname, argTuple) 334 335 336# ----------------------------------------------------------------------------- 337# Don't use any functions beyond this point; private section, likely to change. 338# ----------------------------------------------------------------------------- 339_builtin_import = __import__ 340 341 342def _uno_import(name, *optargs, **kwargs): 343 """Overrides built-in import to allow directly importing LibreOffice classes.""" 344 345 try: 346 return _builtin_import(name, *optargs, **kwargs) 347 except ImportError as e: 348 # process optargs 349 globals, locals, fromlist = list(optargs)[:3] + [kwargs.get('globals', {}), kwargs.get('locals', {}), 350 kwargs.get('fromlist', [])][len(optargs):] 351 352 # from import form only, but skip if a uno lookup has already failed 353 if not fromlist or hasattr(e, '_uno_import_failed'): 354 raise 355 356 # hang onto exception for possible use on subsequent uno lookup failure 357 py_import_exc = e 358 359 mod = None 360 d = sys.modules 361 362 for module in name.split("."): 363 if module in d: 364 mod = d[module] 365 else: 366 # How to create a module ?? 367 mod = pyuno.__class__(module) 368 369 d = mod.__dict__ 370 371 RuntimeException = pyuno.getClass("com.sun.star.uno.RuntimeException") 372 373 for class_name in fromlist: 374 if class_name not in d: 375 failed = False 376 377 try: 378 # check for structs, exceptions or interfaces 379 d[class_name] = pyuno.getClass(name + "." + class_name) 380 except RuntimeException: 381 # check for enums 382 try: 383 d[class_name] = Enum(name, class_name) 384 except RuntimeException: 385 # check for constants 386 try: 387 d[class_name] = getConstantByName(name + "." + class_name) 388 except RuntimeException: 389 # check for constant group 390 try: 391 d[class_name] = _impl_getConstantGroupByName(name, class_name) 392 except ValueError: 393 failed = True 394 395 if failed: 396 # We have an import failure, but cannot distinguish between 397 # uno and non-uno errors as uno lookups are attempted for all 398 # "from xxx import yyy" imports following a python failure. 399 # 400 # In Python 3, the original python exception traceback is reused 401 # to help pinpoint the actual failing location. Its original 402 # message, unlike Python 2, is unlikely to be helpful for uno 403 # failures, as it most commonly is just a top level module like 404 # 'com'. So our exception appends the uno lookup failure. 405 # This is more ambiguous, but it plus the traceback should be 406 # sufficient to identify a root cause for python or uno issues. 407 # 408 # Our exception is raised outside of the nested exception 409 # handlers above, to avoid Python 3 nested exception 410 # information for the RuntimeExceptions during lookups. 411 # 412 # Finally, a private attribute is used to prevent further 413 # processing if this failure was in a nested import. That 414 # keeps the exception relevant to the primary failure point, 415 # preventing us from re-processing our own import errors. 416 417 uno_import_exc = ImportError("%s (or '%s.%s' is unknown)" % 418 (py_import_exc, name, class_name)) 419 420 uno_import_exc = uno_import_exc.with_traceback(py_import_exc.__traceback__) 421 422 uno_import_exc._uno_import_failed = True 423 raise uno_import_exc 424 425 return mod 426 427 428try: 429 import __builtin__ 430except ImportError: 431 import builtins as __builtin__ 432 433# hook into the __import__ chain 434__builtin__.__dict__['__import__'] = _uno_import 435 436 437class _ConstantGroup(object): 438 """Represents a group of UNOIDL constants.""" 439 440 __slots__ = ['_constants'] 441 442 def __init__(self, constants): 443 self._constants = constants 444 445 def __dir__(self): 446 return self._constants.keys() 447 448 def __getattr__(self, name): 449 if name in self._constants: 450 return self._constants[name] 451 452 raise AttributeError("The constant '%s' could not be found." % name) 453 454 455def _impl_getConstantGroupByName(module, group): 456 """Gets UNOIDL constant group by name.""" 457 458 constants = Enum('com.sun.star.uno.TypeClass', 'CONSTANTS') 459 one = Enum('com.sun.star.reflection.TypeDescriptionSearchDepth', 'ONE') 460 type_desc_mgr = _component_context.getValueByName('/singletons/com.sun.star.reflection.theTypeDescriptionManager') 461 type_descs = type_desc_mgr.createTypeDescriptionEnumeration(module, (constants,), one) 462 qualified_name = module + '.' + group 463 464 for type_desc in type_descs: 465 if type_desc.Name == qualified_name: 466 return _ConstantGroup(dict( 467 (c.Name.split('.')[-1], c.ConstantValue) 468 for c in type_desc.Constants)) 469 470 raise ValueError("The constant group '%s' could not be found." % qualified_name) 471 472 473def _uno_struct__init__(self, *args, **kwargs): 474 """Initializes a UNO struct. 475 476 Referenced from the pyuno shared library. 477 478 This function can be called with either an already constructed UNO struct, which it 479 will then just reference without copying, or with arguments to create a new UNO struct. 480 """ 481 482 # Check to see if this function was passed an existing UNO struct 483 if len(kwargs) == 0 and len(args) == 1 and getattr(args[0], "__class__", None) == self.__class__: 484 self.__dict__['value'] = args[0] 485 else: 486 struct, used = pyuno._createUnoStructHelper(self.__class__.__pyunostruct__, args, **kwargs) 487 488 for kwarg in kwargs.keys(): 489 if not used.get(kwarg): 490 RuntimeException = pyuno.getClass("com.sun.star.uno.RuntimeException") 491 raise RuntimeException("_uno_struct__init__: unused keyword argument '%s'." % kwarg, None) 492 493 self.__dict__["value"] = struct 494 495 496def _uno_struct__getattr__(self, name): 497 """Gets attribute from UNO struct. 498 499 Referenced from the pyuno shared library. 500 """ 501 502 return getattr(self.__dict__["value"], name) 503 504 505def _uno_struct__setattr__(self, name, value): 506 """Sets attribute on UNO struct. 507 508 Referenced from the pyuno shared library. 509 """ 510 511 return setattr(self.__dict__["value"], name, value) 512 513 514def _uno_struct__repr__(self): 515 """Converts a UNO struct to a printable string. 516 517 Referenced from the pyuno shared library. 518 """ 519 520 return repr(self.__dict__["value"]) 521 522 523def _uno_struct__str__(self): 524 """Converts a UNO struct to a string.""" 525 526 return str(self.__dict__["value"]) 527 528def _uno_struct__ne__(self, other): 529 return not self.__eq__(other) 530 531def _uno_struct__eq__(self, that): 532 """Compares two UNO structs. 533 534 Referenced from the pyuno shared library. 535 """ 536 537 if hasattr(that, "value"): 538 return self.__dict__["value"] == that.__dict__["value"] 539 540 return False 541 542 543def _uno_extract_printable_stacktrace(trace): 544 """Extracts a printable stacktrace. 545 546 Referenced from pyuno shared lib and pythonscript.py. 547 """ 548 549 return ''.join(traceback.format_tb(trace)) 550 551# vim: set shiftwidth=4 softtabstop=4 expandtab: 552