GnuCash  5.6-150-g038405b370+
gnucash_core.py
Go to the documentation of this file.
1 # gnucash_core.py -- High level python wrapper classes for the core parts
2 # of GnuCash
3 #
4 # Copyright (C) 2008 ParIT Worker Co-operative <paritinfo@parit.ca>
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License as
7 # published by the Free Software Foundation; either version 2 of
8 # the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, contact:
17 # Free Software Foundation Voice: +1-617-542-5942
18 # 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
19 # Boston, MA 02110-1301, USA gnu@gnu.org
20 #
21 # @author Mark Jenkins, ParIT Worker Co-operative <mark@parit.ca>
22 # @author Jeff Green, ParIT Worker Co-operative <jeff@parit.ca>
23 
24 # The following is for doxygen
25 
26 
28 
29 
32 
33 
152 
153 
154 
159 
160 import operator
161 
162 from enum import IntEnum
163 from urllib.parse import urlparse
164 
165 from gnucash import gnucash_core_c
166 from gnucash import _sw_core_utils
167 
168 from gnucash.function_class import \
169  ClassFromFunctions, extract_attributes_with_prefix, \
170  default_arguments_decorator, method_function_returns_instance, \
171  methods_return_instance, process_list_convert_to_instance, \
172  method_function_returns_instance_list, methods_return_instance_lists
173 
174 from gnucash.gnucash_core_c import gncInvoiceLookup, gncInvoiceGetInvoiceFromTxn, \
175  gncInvoiceGetInvoiceFromLot, gncEntryLookup, gncInvoiceLookup, \
176  gncCustomerLookup, gncVendorLookup, gncJobLookup, gncEmployeeLookup, \
177  gncTaxTableLookup, gncTaxTableLookupByName, gnc_search_invoice_on_id, \
178  gnc_search_customer_on_id, gnc_search_bill_on_id , \
179  gnc_search_vendor_on_id, gncInvoiceNextID, gncCustomerNextID, \
180  gncVendorNextID, gncTaxTableGetTables, gnc_numeric_zero, \
181  gnc_numeric_create, double_to_gnc_numeric, gnc_numeric_from_string, \
182  gnc_numeric_to_string, gnc_numeric_check
183 
184 from gnucash.deprecation import (
185  deprecated_args_session,
186  deprecated_args_session_init,
187  deprecated_args_session_begin,
188  deprecated
189 )
190 
191 try:
192  import gettext
193 
194  _localedir = _sw_core_utils.gnc_path_get_localedir()
195  gettext.install(_sw_core_utils.GETTEXT_PACKAGE, _localedir)
196 except:
197  print()
198  print("Problem importing gettext!")
199  import traceback
200  import sys
201  exc_type, exc_value, exc_traceback = sys.exc_info()
202  traceback.print_exception(exc_type, exc_value, exc_traceback)
203  print()
204 
205  def _(s):
206  """Null translator function, gettext not available"""
207  return s
208 
209  import builtins
210  builtins.__dict__['_'] = _
211 
212 class GnuCashCoreClass(ClassFromFunctions):
213  _module = gnucash_core_c
214 
215  def do_lookup_create_oo_instance(self, lookup_function, cls, *args):
216  thing = lookup_function(self.get_instance(), *args)
217  if thing != None:
218  thing = cls(instance=thing)
219  return thing
220 
221 
222 class GnuCashBackendException(Exception):
223  def __init__(self, msg, errors):
224  Exception.__init__(self, msg)
225  self.errors = errors
226 
227 
228 class SessionOpenMode(IntEnum):
229  """Mode for opening sessions.
230 
231  This replaces three booleans that were passed in order: ignore_lock, create,
232  and force. It's structured so that one can use it as a bit field with the
233  values in the same order, i.e. ignore_lock = 1 << 2, create_new = 1 << 1, and
234  force_new = 1.
235 
236  enumeration members
237  -------------------
238 
239  SESSION_NORMAL_OPEN = 0 (All False)
240  Open will fail if the URI doesn't exist or is locked.
241 
242  SESSION_NEW_STORE = 2 (False, True, False (create))
243  Create a new store at the URI. It will fail if the store already exists and is found to contain data that would be overwritten.
244 
245  SESSION_NEW_OVERWRITE = 3 (False, True, True (create | force))
246  Create a new store at the URI even if a store already exists there.
247 
248  SESSION_READ_ONLY = 4, (True, False, False (ignore_lock))
249  Open the session read-only, ignoring any existing lock and not creating one if the URI isn't locked.
250 
251  SESSION_BREAK_LOCK = 5 (True, False, True (ignore_lock | force))
252  Open the session, taking over any existing lock.
253 
254  source: lignucash/engine/qofsession.h
255  """
256 
257  SESSION_NORMAL_OPEN = gnucash_core_c.SESSION_NORMAL_OPEN
258  """All False
259  Open will fail if the URI doesn't exist or is locked."""
260 
261  SESSION_NEW_STORE = gnucash_core_c.SESSION_NEW_STORE
262  """False, True, False (create)
263  Create a new store at the URI. It will fail if the store already exists and is found to contain data that would be overwritten."""
264 
265  SESSION_NEW_OVERWRITE = gnucash_core_c.SESSION_NEW_OVERWRITE
266  """False, True, True (create | force)
267  Create a new store at the URI even if a store already exists there."""
268 
269  SESSION_READ_ONLY = gnucash_core_c.SESSION_READ_ONLY
270  """True, False, False (ignore_lock)
271  Open the session read-only, ignoring any existing lock and not creating one if the URI isn't locked."""
272 
273  SESSION_BREAK_LOCK = gnucash_core_c.SESSION_BREAK_LOCK
274  """True, False, True (ignore_lock | force)
275  Open the session, taking over any existing lock."""
276 
277 
279  """A GnuCash book editing session
280 
281  To commit changes to the session you may need to call save,
282  (this is always the case with the file backend).
283 
284  When you're down with a session you may need to call end()
285 
286  Every Session has a Book in the book attribute, which you'll definitely
287  be interested in, as every GnuCash entity (Transaction, Split, Vendor,
288  Invoice..) is associated with a particular book where it is stored.
289  """
290 
291  @deprecated_args_session_init
292  def __init__(self, book_uri=None, mode=None, instance=None, book=None):
293  """!
294  A convenient constructor that allows you to specify a book URI,
295  begin the session, and load the book.
296 
297  This can give you the power of calling
298  qof_session_new, qof_session_begin, and qof_session_load all in one!
299 
300  qof_session_load is only called if url scheme is "xml" and
301  mode is SESSION_NEW_STORE or SESSION_NEW_OVERWRITE
302 
303  @param book_uri must be a string in the form of a URI/URL. The access
304  method specified depends on the loaded backends. Paths may be relative
305  or absolute. If the path is relative, that is if the argument is
306  "file://somefile.xml", then the current working directory is
307  assumed. Customized backends can choose to search other
308  application-specific directories or URI schemes as well.
309  It be None to skip the calls to qof_session_begin and
310  qof_session_load.
311 
312  @param instance argument can be passed if new Session is used as a
313  wrapper for an existing session instance
314 
315  @param mode The SessionOpenMode.
316  @note SessionOpenMode replaces deprecated ignore_lock, is_new and force_new.
317 
318  @par SessionOpenMode
319  `SESSION_NORMAL_OPEN`: Find an existing file or database at the provided uri and
320  open it if it is unlocked. If it is locked post a QOF_BACKEND_LOCKED error.
321  @par
322  `SESSION_NEW_STORE`: Check for an existing file or database at the provided
323  uri and if none is found, create it. If the file or database exists post a
324  QOF_BACKED_STORE_EXISTS and return.
325  @par
326  `SESSION_NEW_OVERWRITE`: Create a new file or database at the provided uri,
327  deleting any existing file or database.
328  @par
329  `SESSION_READ_ONLY`: Find an existing file or database and open it without
330  disturbing the lock if it exists or setting one if not. This will also set a
331  flag on the book that will prevent many elements from being edited and will
332  prevent the backend from saving any edits.
333  @par
334  `SESSION_BREAK_LOCK`: Find an existing file or database, lock it, and open
335  it. If there is already a lock replace it with a new one for this session.
336 
337  @par Errors
338  qof_session_begin() signals failure by queuing errors. After it completes use
339  qof_session_get_error() and test that the value is `ERROR_BACKEND_NONE` to
340  determine that the session began successfully.
341 
342  @exception as begin() and load() are wrapped with raise_backend_errors_after_call()
343  this function can raise a GnuCashBackendException. If it does,
344  you don't need to cleanup and call end() and destroy(), that is handled
345  for you, and the exception is raised.
346  """
347  if instance is not None:
348  GnuCashCoreClass.__init__(self, instance=instance)
349  else:
350  if book is None:
351  book = Book()
352  GnuCashCoreClass.__init__(self, book)
353 
354  if book_uri is not None:
355  try:
356  if mode is None:
357  mode = SessionOpenMode.SESSION_NORMAL_OPEN
358  self.begin(book_uri, mode)
359  except GnuCashBackendException as backend_exception:
360  self.end()
361  self.destroy()
362  raise
363 
364  def __enter__(self):
365  return self
366 
367  def __exit__(self, exc_type, exc_value, traceback):
368  # Roll back changes on exception by not calling save. Only works for XMl backend.
369  if not exc_type:
370  self.save()
371  self.end()
372 
373  def raise_backend_errors(self, called_function="qof_session function"):
374  """Raises a GnuCashBackendException if there are outstanding
375  QOF_BACKEND errors.
376 
377  set called_function to name the function that was last called
378  """
379  errors = self.pop_all_errors()
380  if errors != ():
382  "call to %s resulted in the "
383  "following errors, %s" % (called_function, backend_error_dict[errors[0]]),
384  errors )
385 
386  def generate_errors(self):
387  """A generator that yields any outstanding QofBackend errors
388  """
389  while self.get_error() is not ERR_BACKEND_NO_ERR:
390  error = self.pop_error()
391  yield error
392 
393  def pop_all_errors(self):
394  """Returns any accumulated qof backend errors as a tuple
395  """
396  return tuple( self.generate_errors() )
397 
398  # STATIC METHODS
399  @staticmethod
400  def raise_backend_errors_after_call(function, *args, **kwargs):
401  """A function decorator that results in a call to
402  raise_backend_errors after execution.
403  """
404  def new_function(self, *args, **kwargs):
405  return_value = function(self, *args, **kwargs)
406  self.raise_backend_errors(function.__name__)
407  return return_value
408  return new_function
409 
411  """A Book encapsulates all of the GnuCash data, it is the place where
412  all GnuCash entities (Transaction, Split, Vendor, Invoice...), are
413  stored. You'll notice that all of the constructors for those entities
414  need a book to be associated with.
415 
416  The most common way to get a book is through the book property in the
417  Session class, that is, create a session that connects to some storage,
418  such as through 'my_session = Session('file:my_books.xac')', and access
419  the book via the book property, 'my_session.book'
420 
421  If you would like to create a Book without any backing storage, call the
422  Book constructor without any parameters, 'Book()'. You can later merge
423  such a book into a book with actual store by using merge_init.
424 
425  Methods of interest
426  get_root_account -- Returns the root level Account
427  get_table -- Returns a commodity lookup table, of type GncCommodityTable
428  """
429  def InvoiceLookup(self, guid):
430  from gnucash.gnucash_business import Invoice
431  return self.do_lookup_create_oo_instance(
432  gncInvoiceLookup, Invoice, guid.get_instance() )
433 
434  def EntryLookup(self, guid):
435  from gnucash.gnucash_business import Entry
436  return self.do_lookup_create_oo_instance(
437  gncEntryLookup, Entry, guid.get_instance() )
438 
439  def CustomerLookup(self, guid):
440  from gnucash.gnucash_business import Customer
441  return self.do_lookup_create_oo_instance(
442  gncCustomerLookup, Customer, guid.get_instance())
443 
444  def JobLookup(self, guid):
445  from gnucash.gnucash_business import Job
446  return self.do_lookup_create_oo_instance(
447  gncJobLookup, Job, guid.get_instance() )
448 
449  def VendorLookup(self, guid):
450  from gnucash.gnucash_business import Vendor
451  return self.do_lookup_create_oo_instance(
452  gncVendorLookup, Vendor, guid.get_instance() )
453 
454  def EmployeeLookup(self, guid):
455  from gnucash.gnucash_business import Employee
456  return self.do_lookup_create_oo_instance(
457  gncEmployeeLookup, Employee, guid.get_instance() )
458 
459  def TaxTableLookup(self, guid):
460  from gnucash.gnucash_business import TaxTable
461  return self.do_lookup_create_oo_instance(
462  gncTaxTableLookup, TaxTable, guid.get_instance() )
463 
464  def TaxTableLookupByName(self, name):
465  from gnucash.gnucash_business import TaxTable
466  return self.do_lookup_create_oo_instance(
467  gncTaxTableLookupByName, TaxTable, name)
468 
469  def TaxTableGetTables(self):
470  from gnucash.gnucash_business import TaxTable
471  return [ TaxTable(instance=item) for item in gncTaxTableGetTables(self.instance) ]
472 
473  def BillLookupByID(self, id):
474  from gnucash.gnucash_business import Bill
475  return self.do_lookup_create_oo_instance(
476  gnc_search_bill_on_id, Bill, id)
477 
478  def InvoiceLookupByID(self, id):
479  from gnucash.gnucash_business import Invoice
480  return self.do_lookup_create_oo_instance(
481  gnc_search_invoice_on_id, Invoice, id)
482 
483  def CustomerLookupByID(self, id):
484  from gnucash.gnucash_business import Customer
485  return self.do_lookup_create_oo_instance(
486  gnc_search_customer_on_id, Customer, id)
487 
488  def VendorLookupByID(self, id):
489  from gnucash.gnucash_business import Vendor
490  return self.do_lookup_create_oo_instance(
491  gnc_search_vendor_on_id, Vendor, id)
492 
493  def InvoiceNextID(self, customer):
494  ''' Return the next invoice ID.
495  '''
496  from gnucash.gnucash_core_c import gncInvoiceNextID
497  return gncInvoiceNextID(self.get_instance(),customer.GetEndOwner().get_instance()[1])
498 
499  def BillNextID(self, vendor):
500  ''' Return the next Bill ID. '''
501  from gnucash.gnucash_core_c import gncInvoiceNextID
502  return gncInvoiceNextID(self.get_instance(),vendor.GetEndOwner().get_instance()[1])
503 
504  def CustomerNextID(self):
505  ''' Return the next Customer ID. '''
506  from gnucash.gnucash_core_c import gncCustomerNextID
507  return gncCustomerNextID(self.get_instance())
508 
509  def VendorNextID(self):
510  ''' Return the next Vendor ID. '''
511  from gnucash.gnucash_core_c import gncVendorNextID
512  return gncVendorNextID(self.get_instance())
513 
515  """Object used by GnuCash to store all numbers. Always consists of a
516  numerator and denominator.
517 
518  The constants GNC_DENOM_AUTO,
519  GNC_HOW_RND_FLOOR, GNC_HOW_RND_CEIL, GNC_HOW_RND_TRUNC,
520  GNC_HOW_RND_PROMOTE, GNC_HOW_RND_ROUND_HALF_DOWN,
521  GNC_HOW_RND_ROUND_HALF_UP, GNC_HOW_RND_ROUND, GNC_HOW_RND_NEVER,
522  GNC_HOW_DENOM_EXACT, GNC_HOW_DENOM_REDUCE, GNC_HOW_DENOM_LCD,
523  and GNC_HOW_DENOM_FIXED are available for arithmetic
524  functions like GncNumeric.add
525 
526  Look at gnc-numeric.h to see how to use these
527  """
528 
529  def __init__(self, *args, **kargs):
530  """Constructor that supports the following formats:
531  * No arguments defaulting to zero: eg. GncNumeric() == 0/1
532  * A integer: e.g. GncNumeric(1) == 1/1
533  * Numerator and denominator intager pair: eg. GncNumeric(1, 2) == 1/2
534  * A floating point number: e.g. GncNumeric(0.5) == 1/2
535  * A floating point number with defined conversion: e.g.
536  GncNumeric(0.5, GNC_DENOM_AUTO,
537  GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER) == 1/2
538  * A string: e.g. GncNumeric("1/2") == 1/2
539  """
540  if 'instance' not in kargs:
541  kargs['instance'] = GncNumeric.__args_to_instance(args)
542  GnuCashCoreClass.__init__(self, [], **kargs)
543 
544  @staticmethod
545  def __args_to_instance(args):
546  if len(args) == 0:
547  return gnc_numeric_zero()
548  elif len(args) == 1:
549  arg = args[0]
550  if isinstance(arg, int):
551  return gnc_numeric_create(arg, 1)
552  elif isinstance(arg, float):
553  return double_to_gnc_numeric(arg, GNC_DENOM_AUTO, GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER)
554  elif isinstance(arg, str):
555  instance = gnc_numeric_from_string(arg)
556  if gnc_numeric_check(instance):
557  raise TypeError('Failed to convert to GncNumeric: ' + str(args))
558  return instance
559  elif isinstance(arg, GncNumeric):
560  return arg.instance
561  else:
562  raise TypeError('Only single int/float/str/GncNumeric allowed: ' + str(args))
563  elif len(args) == 2:
564  if isinstance(args[0], int) and isinstance(args[1], int):
565  return gnc_numeric_create(*args)
566  else:
567  raise TypeError('Only two ints allowed: ' + str(args))
568  elif len(args) == 3:
569  if isinstance(args[0], float) \
570  and isinstance(args[1], int) \
571  and type(args[2]) == type(GNC_HOW_DENOM_FIXED):
572  return double_to_gnc_numeric(*args)
573  else:
574  raise TypeError('Only (float, int, GNC_HOW_RND_*) allowed: ' + str(args))
575  else:
576  raise TypeError('Required single int/float/str or two ints: ' + str(args))
577 
578  # from https://docs.python.org/3/library/numbers.html#numbers.Integral
579  # and https://github.com/python/cpython/blob/3.7/Lib/fractions.py
580 
581  def _operator_fallbacks(monomorphic_operator, fallback_operator):
582  """fallbacks are not needed except for method name,
583  keep for possible later use"""
584  def forward(a, b):
585  if isinstance(b, GncNumeric):
586  return monomorphic_operator(a, b)
587  if isinstance(b, (int, float)):
588  return monomorphic_operator(a, GncNumeric(b))
589  else:
590  return NotImplemented
591  forward.__name__ = '__' + fallback_operator.__name__ + '__'
592  forward.__doc__ = monomorphic_operator.__doc__
593 
594  def reverse(b, a):
595  if isinstance(a, (GncNumeric, int, float)):
596  return forward(b, a)
597  else:
598  return NotImplemented
599  reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
600  reverse.__doc__ = monomorphic_operator.__doc__
601 
602  return forward, reverse
603 
604  def _add(a, b):
605  return a.add(b, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND)
606 
607  def _sub(a, b):
608  return a.sub(b, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND)
609 
610  def _mul(a, b):
611  return a.mul(b, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND)
612 
613  def _div(a, b):
614  return a.div(b, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND)
615 
616  def _floordiv(a, b):
617  return a.div(b, 1, GNC_HOW_RND_TRUNC)
618 
619  __add__, __radd__ = _operator_fallbacks(_add, operator.add)
620  __iadd__ = __add__
621  __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub)
622  __isub__ = __sub__
623  __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul)
624  __imul__ = __mul__
625  __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)
626  __itruediv__ = __truediv__
627  __floordiv__, __rfloordiv__ = _operator_fallbacks(_floordiv, operator.floordiv)
628  __ifloordiv__ = __floordiv__
629 
630  # Comparisons derived from https://github.com/python/cpython/blob/3.7/Lib/fractions.py
631  def _lt(a, b):
632  return a.compare(b) == -1
633 
634  def _gt(a, b):
635  return a.compare(b) == 1
636 
637  def _le(a, b):
638  return a.compare(b) in (0,-1)
639 
640  def _ge(a, b):
641  return a.compare(b) in (0,1)
642 
643  def _eq(a, b):
644  return a.compare(b) == 0
645 
646  def _richcmp(self, other, op):
647  """Helper for comparison operators, for internal use only.
648  Implement comparison between a GncNumeric instance `self`,
649  and either another GncNumeric instance, an int or a float
650  `other`. If `other` is not an instance of that kind, return
651  NotImplemented. `op` should be one of the six standard
652  comparison operators. The comparisons are based on
653  GncNumeric.compare().
654  """
655  import math
656  if isinstance(other, GncNumeric):
657  return op(other)
658  elif isinstance(other, (int, float)):
659  return op(GncNumeric(other))
660  else:
661  return NotImplemented
662 
663  def __lt__(a, b):
664  """a < b"""
665  return a._richcmp(b, a._lt)
666 
667  def __gt__(a, b):
668  """a > b"""
669  return a._richcmp(b, a._gt)
670 
671  def __le__(a, b):
672  """a <= b"""
673  return a._richcmp(b, a._le)
674 
675  def __ge__(a, b):
676  """a >= b"""
677  return a._richcmp(b, a._ge)
678 
679  def __eq__(a, b):
680  """a == b"""
681  return a._richcmp(b, a._eq)
682 
683  def __bool__(a):
684  """a != 0"""
685  return bool(a.num())
686 
687  def __float__(self):
688  return self.to_double()
689 
690  def __int__(self):
691  return int(self.to_double())
692 
693  def __pos__(a):
694  """+a"""
695  return GncNumeric(a.num(), a.denom())
696 
697  def __neg__(a):
698  """-a"""
699  return a.neg()
700 
701  def __abs__(a):
702  """abs(a)"""
703  return a.abs()
704 
705  def to_fraction(self):
706  from fractions import Fraction
707  return Fraction(self.num(), self.denom())
708 
709  def __str__(self):
710  """Returns a human readable numeric value string as UTF8."""
711  return gnc_numeric_to_string(self.instance)
712 
714  '''
715  Each priceEach price in the database represents an "instantaneous"
716  quote for a given commodity with respect to another commodity.
717  For example, a given price might represent the value of LNUX in USD on 2001-02-03.
718 
719  Fields:
720  * commodity: the item being priced.
721  * currency: the denomination of the value of the item being priced.
722  * value: the value of the item being priced.
723  * time: the time the price was valid.
724  * source: a string describing the source of the quote. These strings will be something like this:
725  "Finance::Quote", "user:misc", "user:foo", etc. If the quote came from a user, as a matter of policy,
726  you *must* prefix the string you give with "user:". For now, the only other reserved values are
727  "Finance::Quote" and "old-file-import". Any string used must be added to the source_list array in
728  dialog-price-edit-db.c so that it can be properly translated. (There are unfortunately many strings
729  in users' databases, so this string must be translated on output instead of always being used in untranslated form).
730  * type: the type of quote - types possible right now are bid, ask, last, nav, and
731  unknown.Each price in the database represents an "instantaneous" quote for a given
732  commodity with respect to another commodity.
733  For example, a given price might represent the value of LNUX in USD on 2001-02-03.
734 
735  See also https://code.gnucash.org/docs/head/group__Price.html
736  '''
737  _new_instance = 'gnc_price_create'
738 GncPrice.add_methods_with_prefix('gnc_price_')
739 
740 
742  '''
743  a simple price database for gnucash.
744  The PriceDB is intended to be a database of price quotes, or more specifically,
745  a database of GNCPrices. For the time being, it is still a fairly simple
746  database supporting only fairly simple queries. It is expected that new
747  queries will be added as needed, and that there is some advantage to delaying
748  complex queries for now in the hope that we get a real DB implementation
749  before they're really needed.
750 
751  Every QofBook contains a GNCPriceDB, accessible via gnc_pricedb_get_db.
752 
753  Definition in file gnc-pricedb.h.
754  See also https://code.gnucash.org/docs/head/gnc-pricedb_8h.html
755  '''
756 
757 @deprecated("Use gnc_pricedb_latest_before_t64")
758 def gnc_pricedb_lookup_latest_before_t64(self, commodity, currency, date):
759  return self.lookup_nearest_before_t64(commodity, currency, date)
760 
761 GncPriceDB.add_method('gnc_pricedb_lookup_latest_before_t64', 'lookup_latest_before_t64')
762 
763 GncPriceDB.lookup_latest_before_t64 = method_function_returns_instance(GncPriceDB.lookup_latest_before_t64, GncPrice)
764 
765 GncPriceDB.add_methods_with_prefix('gnc_pricedb_')
766 PriceDB_dict = {
767  'lookup_latest' : GncPrice,
768  'lookup_nearest_in_time64' : GncPrice,
769  'lookup_nearest_before_t64' : GncPrice,
770  'convert_balance_latest_price' : GncNumeric,
771  'convert_balance_nearest_price_t64' : GncNumeric,
772  }
773 methods_return_instance(GncPriceDB,PriceDB_dict)
774 GncPriceDB.get_prices = method_function_returns_instance_list(
775  GncPriceDB.get_prices, GncPrice )
776 
778 
780  """A CommodityTable provides a way to store and lookup commodities.
781  Commodities are primarily currencies, but other tradable things such as
782  stocks, mutual funds, and material substances are possible.
783 
784  Users of this library should not create their own CommodityTable, instead
785  the get_table method from the Book class should be used.
786 
787  This table is automatically populated with the GnuCash default commodity's
788  which includes most of the world's currencies.
789  """
790 
791  def _get_namespaces_py(self):
792  return [ns.get_name() for ns in self.get_namespaces_list()]
793 
795  pass
796 
797 class GncLot(GnuCashCoreClass):
798  def GetInvoiceFromLot(self):
799  from gnucash.gnucash_business import Invoice
800  return self.do_lookup_create_oo_instance(
801  gncInvoiceGetInvoiceFromLot, Invoice )
802 
804  """A GnuCash Transaction
805 
806  Consists of at least one (generally two) splits to represent a transaction
807  between two accounts.
808 
809 
810  Has a GetImbalance() method that returns a list of all the imbalanced
811  currencies. Each list item is a two element tuple, the first element is
812  the imbalanced commodity, the second element is the value.
813 
814  Warning, the commodity.get_instance() value can be None when there
815  is no currency set for the transaction.
816  """
817  _new_instance = 'xaccMallocTransaction'
818  def GetNthSplit(self, n):
819  return self.GetSplitList().pop(n)
820 
821  def GetInvoiceFromTxn(self):
822  from gnucash.gnucash_business import Transaction
823  return self.do_lookup_create_oo_instance(
824  gncInvoiceGetInvoiceFromTxn, Transaction )
825 
826  def __eq__(self, other):
827  return self.Equal(other, True, False, False, False)
828 
829 def decorate_monetary_list_returning_function(orig_function):
830  def new_function(self, *args):
831  """decorate function that returns list of gnc_monetary to return tuples of GncCommodity and GncNumeric
832 
833  Args:
834  *args: Variable length argument list. Will get passed to orig_function
835 
836  Returns:
837  array of tuples: (GncCommodity, GncNumeric)
838 
839  ToDo:
840  Maybe this function should better reside in module function_class (?)"""
841  # warning, item.commodity has been shown to be None
842  # when the transaction doesn't have a currency
843  return [(GncCommodity(instance=item.commodity),
844  GncNumeric(instance=item.value))
845  for item in orig_function(self, *args) ]
846  return new_function
847 
849  """A GnuCash Split
850 
851  The most basic representation of a movement of currency from one account to
852  another.
853  """
854  _new_instance = 'xaccMallocSplit'
855 
856  def __eq__(self, other):
857  return self.Equal(other, True, False, False)
858 
860  """A GnuCash Account.
861 
862  A fundamental entity in accounting, an Account provides representation
863  for a financial object, such as a ACCT_TYPE_BANK account, an
864  ACCT_TYPE_ASSET (like a building),
865  a ACCT_TYPE_LIABILITY (such as a bank loan), a summary of some type of
866  ACCT_TYPE_EXPENSE, or a summary of some source of ACCT_TYPE_INCOME .
867 
868  The words in upper case are the constants that GnuCash and this library uses
869  to describe account type. Here is the full list:
870  ACCT_TYPE_ASSET, ACCT_TYPE_BANK, ACCT_TYPE_CASH, ACCT_TYPE_CHECKING, \
871  ACCT_TYPE_CREDIT, ACCT_TYPE_EQUITY, ACCT_TYPE_EXPENSE, ACCT_TYPE_INCOME, \
872  ACCT_TYPE_LIABILITY, ACCT_TYPE_MUTUAL, ACCT_TYPE_PAYABLE, \
873  ACCT_TYPE_RECEIVABLE, ACCT_TYPE_STOCK, ACCT_TYPE_ROOT, ACCT_TYPE_TRADING
874 
875  These are not strings, they are attributes you can import from this
876  module
877  """
878  _new_instance = 'xaccMallocAccount'
879 
881  _new_instance = 'guid_new_return'
882 
883 # Session
884 Session.add_constructor_and_methods_with_prefix('qof_session_', 'new')
885 
886 def one_arg_default_none(function):
887  return default_arguments_decorator(function, None, None)
888 Session.decorate_functions(one_arg_default_none, "load", "save")
889 
890 Session.decorate_functions( Session.raise_backend_errors_after_call,
891  "begin", "load", "save", "end")
892 Session.decorate_method(default_arguments_decorator, "begin", None, mode=SessionOpenMode.SESSION_NORMAL_OPEN)
893 Session.decorate_functions(deprecated_args_session_begin, "begin")
894 
895 Session.get_book = method_function_returns_instance(
896  Session.get_book, Book )
897 
898 Session.book = property( Session.get_book )
899 
900 # import all of the session backend error codes into this module
901 this_module_dict = globals()
902 for error_name, error_value, error_name_after_prefix in \
903  extract_attributes_with_prefix(gnucash_core_c, 'ERR_'):
904  this_module_dict[ error_name ] = error_value
905 
906 #backend error codes used for reverse lookup
907 backend_error_dict = {}
908 for error_name, error_value, error_name_after_prefix in \
909  extract_attributes_with_prefix(gnucash_core_c, 'ERR_'):
910  backend_error_dict[ error_value ] = error_name
911 
912 # GncNumeric denominator computation schemes
913 # Used for the denom argument in arithmetic functions like GncNumeric.add
914 from gnucash.gnucash_core_c import GNC_DENOM_AUTO
915 
916 # GncNumeric rounding instructions
917 # used for the how argument in arithmetic functions like GncNumeric.add
918 from gnucash.gnucash_core_c import \
919  GNC_HOW_RND_FLOOR, GNC_HOW_RND_CEIL, GNC_HOW_RND_TRUNC, \
920  GNC_HOW_RND_PROMOTE, GNC_HOW_RND_ROUND_HALF_DOWN, \
921  GNC_HOW_RND_ROUND_HALF_UP, GNC_HOW_RND_ROUND, GNC_HOW_RND_NEVER
922 
923 # GncNumeric denominator types
924 # used for the how argument in arithmetic functions like GncNumeric.add
925 from gnucash.gnucash_core_c import \
926  GNC_HOW_DENOM_EXACT, GNC_HOW_DENOM_REDUCE, GNC_HOW_DENOM_LCD, \
927  GNC_HOW_DENOM_FIXED, GNC_HOW_DENOM_SIGFIG
928 
929 # import account types
930 from gnucash.gnucash_core_c import \
931  ACCT_TYPE_ASSET, ACCT_TYPE_BANK, ACCT_TYPE_CASH, ACCT_TYPE_CHECKING, \
932  ACCT_TYPE_CREDIT, ACCT_TYPE_EQUITY, ACCT_TYPE_EXPENSE, ACCT_TYPE_INCOME, \
933  ACCT_TYPE_LIABILITY, ACCT_TYPE_MUTUAL, ACCT_TYPE_PAYABLE, \
934  ACCT_TYPE_RECEIVABLE, ACCT_TYPE_STOCK, ACCT_TYPE_ROOT, ACCT_TYPE_TRADING
935 
936 #Book
937 Book.add_constructor_and_methods_with_prefix('qof_book_', 'new')
938 Book.add_method('gnc_book_get_root_account', 'get_root_account')
939 Book.add_method('gnc_book_set_root_account', 'set_root_account')
940 Book.add_method('gnc_commodity_table_get_table', 'get_table')
941 Book.add_method('gnc_pricedb_get_db', 'get_price_db')
942 Book.add_method('qof_book_increment_and_format_counter', 'increment_and_format_counter')
943 
944 #Functions that return Account
945 Book.get_root_account = method_function_returns_instance(
946  Book.get_root_account, Account )
947 #Functions that return GncCommodityTable
948 Book.get_table = method_function_returns_instance(
949  Book.get_table, GncCommodityTable )
950 #Functions that return GNCPriceDB
951 Book.get_price_db = method_function_returns_instance(
952  Book.get_price_db, GncPriceDB)
953 
954 # GncNumeric
955 GncNumeric.add_constructor_and_methods_with_prefix('gnc_numeric_', 'create')
956 
957 gncnumeric_dict = {
958  'same' : GncNumeric,
959  'add' : GncNumeric,
960  'sub' : GncNumeric,
961  'mul' : GncNumeric,
962  'div' : GncNumeric,
963  'neg' : GncNumeric,
964  'abs' : GncNumeric,
965  'add_fixed' : GncNumeric,
966  'sub_fixed' : GncNumeric,
967  'convert' : GncNumeric,
968  'reduce' : GncNumeric,
969  'invert' : GncNumeric
970  }
971 methods_return_instance(GncNumeric, gncnumeric_dict)
972 
973 # GncCommodity
974 GncCommodity.add_constructor_and_methods_with_prefix('gnc_commodity_', 'new')
975 #Functions that return GncCommodity
976 GncCommodity.clone = method_function_returns_instance(
977  GncCommodity.clone, GncCommodity )
978 
979 # GncCommodityTable
980 GncCommodityTable.add_methods_with_prefix('gnc_commodity_table_')
981 commoditytable_dict = {
982  'lookup' : GncCommodity,
983  'lookup_unique' : GncCommodity,
984  'find_full' : GncCommodity,
985  'insert' : GncCommodity,
986  'add_namespace': GncCommodityNamespace,
987  'find_namespace': GncCommodityNamespace,
988  }
989 methods_return_instance(GncCommodityTable, commoditytable_dict)
990 
991 methods_return_instance_lists(
992  GncCommodityTable, { 'get_namespaces_list': GncCommodityNamespace,
993  'get_commodities': GncCommodity,
994  'get_quotable_commodities': GncCommodity,
995 
996  } )
997 setattr(GncCommodityTable, 'get_namespaces', getattr(GncCommodityTable, '_get_namespaces_py'))
998 
999 # GncCommodityNamespace
1000 GncCommodityNamespace.add_methods_with_prefix('gnc_commodity_namespace_')
1001 GncCommodityNamespace.get_commodity_list = \
1002  method_function_returns_instance_list(
1003  GncCommodityNamespace.get_commodity_list, GncCommodity )
1004 
1005 # GncLot
1006 GncLot.add_constructor_and_methods_with_prefix('gnc_lot_', 'new')
1007 
1008 gnclot_dict = {
1009  'get_account' : Account,
1010  'get_book' : Book,
1011  'get_earliest_split' : Split,
1012  'get_latest_split' : Split,
1013  'get_balance' : GncNumeric,
1014  'lookup' : GncLot,
1015  'make_default' : GncLot
1016  }
1017 methods_return_instance(GncLot, gnclot_dict)
1018 
1019 # Transaction
1020 Transaction.add_methods_with_prefix('xaccTrans')
1021 Transaction.add_method('gncTransGetGUID', 'GetGUID')
1022 
1023 Transaction.add_method('xaccTransGetDescription', 'GetDescription')
1024 Transaction.add_method('xaccTransDestroy', 'Destroy')
1025 
1026 trans_dict = {
1027  'GetSplit': Split,
1028  'FindSplitByAccount': Split,
1029  'Clone': Transaction,
1030  'Reverse': Transaction,
1031  'GetReversedBy': Transaction,
1032  'GetImbalanceValue': GncNumeric,
1033  'GetAccountValue': GncNumeric,
1034  'GetAccountAmount': GncNumeric,
1035  'GetAccountConvRate': GncNumeric,
1036  'GetAccountBalance': GncNumeric,
1037  'GetCurrency': GncCommodity,
1038  'GetGUID': GUID
1039  }
1040 
1041 methods_return_instance(Transaction, trans_dict)
1042 methods_return_instance_lists(
1043  Transaction, { 'GetSplitList': Split,
1044  })
1045 Transaction.decorate_functions(
1046  decorate_monetary_list_returning_function, 'GetImbalance')
1047 
1048 # Split
1049 Split.add_methods_with_prefix('xaccSplit')
1050 Split.add_method('gncSplitGetGUID', 'GetGUID')
1051 Split.add_method('xaccSplitDestroy', 'Destroy')
1052 
1053 split_dict = {
1054  'GetBook': Book,
1055  'GetAccount': Account,
1056  'GetParent': Transaction,
1057  'Lookup': Split,
1058  'GetOtherSplit': Split,
1059  'GetAmount': GncNumeric,
1060  'GetValue': GncNumeric,
1061  'GetSharePrice': GncNumeric,
1062  'ConvertAmount': GncNumeric,
1063  'GetBaseValue': GncNumeric,
1064  'GetBalance': GncNumeric,
1065  'GetClearedBalance': GncNumeric,
1066  'GetReconciledBalance': GncNumeric,
1067  'VoidFormerAmount': GncNumeric,
1068  'VoidFormerValue': GncNumeric,
1069  'GetGUID': GUID
1070  }
1071 methods_return_instance(Split, split_dict)
1072 
1073 Split.account = property( Split.GetAccount, Split.SetAccount )
1074 Split.parent = property( Split.GetParent, Split.SetParent )
1075 
1076 # Account
1077 Account.add_methods_with_prefix('xaccAccount')
1078 Account.add_methods_with_prefix('gnc_account_')
1079 Account.add_method('gncAccountGetGUID', 'GetGUID')
1080 Account.add_method('xaccAccountGetPlaceholder', 'GetPlaceholder')
1081 
1082 account_dict = {
1083  'get_book' : Book,
1084  'Lookup' : Account,
1085  'get_parent' : Account,
1086  'get_root' : Account,
1087  'nth_child' : Account,
1088  'lookup_by_code' : Account,
1089  'lookup_by_name' : Account,
1090  'lookup_by_full_name' : Account,
1091  'FindTransByDesc' : Transaction,
1092  'FindSplitByDesc' : Split,
1093  'GetBalance' : GncNumeric,
1094  'GetClearedBalance' : GncNumeric,
1095  'GetReconciledBalance' : GncNumeric,
1096  'GetPresentBalance' : GncNumeric,
1097  'GetProjectedMinimumBalance' : GncNumeric,
1098  'GetBalanceAsOfDate' : GncNumeric,
1099  'ConvertBalanceToCurrency' : GncNumeric,
1100  'ConvertBalanceToCurrencyAsOfDate' : GncNumeric,
1101  'GetBalanceInCurrency' : GncNumeric,
1102  'GetClearedBalanceInCurrency' : GncNumeric,
1103  'GetReconciledBalanceInCurrency' : GncNumeric,
1104  'GetPresentBalanceInCurrency' : GncNumeric,
1105  'GetProjectedMinimumBalanceInCurrency' : GncNumeric,
1106  'GetBalanceAsOfDateInCurrency' : GncNumeric,
1107  'GetBalanceChangeForPeriod' : GncNumeric,
1108  'GetCommodity' : GncCommodity,
1109  'GetGUID': GUID
1110  }
1111 methods_return_instance(Account, account_dict)
1112 methods_return_instance_lists(
1113  Account, { 'GetSplitList': Split,
1114  'get_children': Account,
1115  'get_children_sorted': Account,
1116  'get_descendants': Account,
1117  'get_descendants_sorted': Account
1118  })
1119 Account.name = property( Account.GetName, Account.SetName )
1120 
1121 #GUID
1122 GUID.add_methods_with_prefix('guid_')
1123 GUID.add_method('xaccAccountLookup', 'AccountLookup')
1124 GUID.add_method('xaccTransLookup', 'TransLookup')
1125 GUID.add_method('xaccSplitLookup', 'SplitLookup')
1126 
1127 
1128 GUID.add_method('guid_to_string', 'to_string')
1129 #GUID.add_method('string_to_guid', 'string_to_guid')
1130 
1131 guid_dict = {
1132  'copy' : GUID,
1133  'TransLookup': Transaction,
1134  'AccountLookup': Account,
1135  'SplitLookup': Split
1136  }
1137 methods_return_instance(GUID, guid_dict)
1138 
1139 #GUIDString
1141  pass
1142 
1143 GUIDString.add_constructor_and_methods_with_prefix('string_', 'to_guid')
1144 
1145 #Query
1146 from gnucash.gnucash_core_c import \
1147  QOF_QUERY_AND, \
1148  QOF_QUERY_OR, \
1149  QOF_QUERY_NAND, \
1150  QOF_QUERY_NOR, \
1151  QOF_QUERY_XOR
1152 
1153 from gnucash.gnucash_core_c import \
1154  QOF_STRING_MATCH_NORMAL, \
1155  QOF_STRING_MATCH_CASEINSENSITIVE
1156 
1157 from gnucash.gnucash_core_c import \
1158  QOF_COMPARE_LT, \
1159  QOF_COMPARE_LTE, \
1160  QOF_COMPARE_EQUAL, \
1161  QOF_COMPARE_GT, \
1162  QOF_COMPARE_GTE, \
1163  QOF_COMPARE_NEQ, \
1164  QOF_COMPARE_CONTAINS, \
1165  QOF_COMPARE_NCONTAINS
1166 
1167 from gnucash.gnucash_core_c import \
1168  QOF_DATE_MATCH_NORMAL, \
1169  QOF_DATE_MATCH_DAY
1170 
1171 from gnucash.gnucash_core_c import \
1172  QOF_NUMERIC_MATCH_DEBIT, \
1173  QOF_NUMERIC_MATCH_CREDIT, \
1174  QOF_NUMERIC_MATCH_ANY
1175 
1176 from gnucash.gnucash_core_c import \
1177  QOF_GUID_MATCH_ANY, \
1178  QOF_GUID_MATCH_NONE, \
1179  QOF_GUID_MATCH_NULL, \
1180  QOF_GUID_MATCH_ALL, \
1181  QOF_GUID_MATCH_LIST_ANY
1182 
1183 from gnucash.gnucash_core_c import \
1184  QOF_CHAR_MATCH_ANY, \
1185  QOF_CHAR_MATCH_NONE
1186 
1187 from gnucash.gnucash_core_c import \
1188  INVOICE_TYPE
1189 
1190 from gnucash.gnucash_core_c import \
1191  INVOICE_IS_PAID
1192 
1194 
1195  def search_for(self, obj_type):
1196  """Set search_for to obj_type
1197 
1198  calls qof_query_search_for. Buffers search string for queries lifetime.
1199  @see https://bugs.gnucash.org/show_bug.cgi?id=796137"""
1200  self.__search_for_buf = obj_type
1201  self._search_for(self.__search_for_buf)
1202 
1203 Query.add_constructor_and_methods_with_prefix('qof_query_', 'create', exclude=["qof_query_search_for"])
1204 
1205 Query.add_method('qof_query_set_book', 'set_book')
1206 Query.add_method('qof_query_search_for', '_search_for')
1207 Query.add_method('qof_query_run', 'run')
1208 Query.add_method('qof_query_add_term', 'add_term')
1209 Query.add_method('qof_query_add_boolean_match', 'add_boolean_match')
1210 Query.add_method('qof_query_add_guid_list_match', 'add_guid_list_match')
1211 Query.add_method('qof_query_add_guid_match', 'add_guid_match')
1212 Query.add_method('qof_query_destroy', 'destroy')
1213 
1215  pass
1216 
1217 QueryStringPredicate.add_constructor_and_methods_with_prefix(
1218  'qof_query_','string_predicate')
1219 
1221  pass
1222 
1223 QueryBooleanPredicate.add_constructor_and_methods_with_prefix(
1224  'qof_query_', 'boolean_predicate')
1225 
1227  pass
1228 
1229 QueryInt32Predicate.add_constructor_and_methods_with_prefix(
1230  'qof_query_', 'int32_predicate')
1231 
1233  pass
1234 
1235 QueryDatePredicate.add_constructor_and_methods_with_prefix(
1236  'qof_query_', 'date_predicate', exclude=["qof_query_date_predicate_get_date"])
1237 QueryDatePredicate.add_method('qof_query_date_predicate_get_date', 'get_date')
1238 
1240  pass
1241 
1242 QueryGuidPredicate.add_constructor_and_methods_with_prefix(
1243  'qof_query_', 'guid_predicate')
1244 
1246  pass
1247 
1248 QueryNumericPredicate.add_constructor_and_methods_with_prefix(
1249  'qof_query_', 'numeric_predicate')
gnc_numeric double_to_gnc_numeric(double in, gint64 denom, gint how)
Convert a floating-point number to a gnc_numeric.
def search_for(self, obj_type)
def raise_backend_errors_after_call(function, args, kwargs)
gchar * gnc_numeric_to_string(gnc_numeric n)
Convert to string.
def BillNextID(self, vendor)
def raise_backend_errors(self, called_function="qof_session function")
def do_lookup_create_oo_instance(self, lookup_function, cls, args)
def InvoiceNextID(self, customer)
def __init__(self, args, kargs)
gnc_numeric gnc_numeric_from_string(const gchar *str)
Read a gnc_numeric from str, skipping any leading whitespace.
def __init__(self, book_uri=None, mode=None, instance=None, book=None)
A convenient constructor that allows you to specify a book URI, begin the session, and load the book.
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.