# Copyright (c) 2024-2026 Karana Dynamics Pty Ltd. All rights reserved.
#
# NOTICE TO USER:
#
# This source code and/or documentation (the "Licensed Materials") is
# the confidential and proprietary information of Karana Dynamics Inc.
# Use of these Licensed Materials is governed by the terms and conditions
# of a separate software license agreement between Karana Dynamics and the
# Licensee ("License Agreement"). Unless expressly permitted under that
# agreement, any reproduction, modification, distribution, or disclosure
# of the Licensed Materials, in whole or in part, to any third party
# without the prior written consent of Karana Dynamics is strictly prohibited.
#
# THE LICENSED MATERIALS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
# KARANA DYNAMICS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, AND
# FITNESS FOR A PARTICULAR PURPOSE.
#
# IN NO EVENT SHALL KARANA DYNAMICS BE LIABLE FOR ANY DAMAGES WHATSOEVER,
# INCLUDING BUT NOT LIMITED TO LOSS OF PROFITS, DATA, OR USE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, WHETHER IN CONTRACT, TORT,
# OR OTHERWISE ARISING OUT OF OR IN CONNECTION WITH THE LICENSED MATERIALS.
#
# U.S. Government End Users: The Licensed Materials are a "commercial item"
# as defined at 48 C.F.R. 2.101, and are provided to the U.S. Government
# only as a commercial end item under the terms of this license.
#
# Any use of the Licensed Materials in individual or commercial software must
# include, in the user documentation and internal source code comments,
# this Notice, Disclaimer, and U.S. Government Use Provision.
"""KCore contains a collection of classes that form core infrastructure for many other classes through Karana software.
Examples include Base and LockingBase which serve as base classes for most simulation-related objects.
"""
import datetime
from typing import TypeVar, cast, overload, TypeAlias, Union, Generic
from traceback import format_stack
# Define Json type alias before loading in pybind11
Json: TypeAlias = dict[str, Union[str, int, float, "Json"]]
from Karana.Core._KCore_pybind11_Py import *
from Karana.Core._KCore_pybind11_Py import deprecated as _deprecated
# Giving credit to Basilisk. See https://github.com/AVSLab/basilisk/blob/19e5538bed96141634fac4570b5b50abb01836a3/src/utilities/deprecated.py
@overload
def deprecated(name: str, removal_date: datetime.date | str, msg: str):
"""
Print a deprecation message.
Parameters
----------
name : str
Name of the class, function, etc. being deprecated.
removal_date : datetime.date | str
The date at which the deprecated class, function, etc. will be removed.
msg : str
A message telling the user how to fix their deprecated code.
"""
... # pragma: no cover. Will not be run by code coverage.
@overload
def deprecated(removal_date: datetime.date | str, msg: str):
"""Use this decorator is used to mark functions or classes as deprecated.
Usage::
@deprecated.deprecated("2024-05-28", "Use MyNewClass")
class MyClass:
...
or::
@deprecated.deprecated("2024-05-28", "myFun is unsafe now")
def myFun(a, b):
...
or::
class ValidClass:
@deprecated.deprecated("2024-05-28", "myMethod is slow, use myBetterMethod")
def myMethod(self, a, b):
...
Parameters
----------
removal_date : datetime.date | str
The date at which the deprecated class, function, etc. will be removed.
msg : str
A message telling the user how to fix their deprecated code.
"""
... # pragma: no cover. Will not be run by code coverage.
def deprecated(*args, **_):
"""Use this decorator is used to mark functions or classes as deprecated.
See overloaded function signatures for details.
"""
if len(args) == 2:
# Decorator
def wrapper(func):
name = f"{func.__module__}.{func.__qualname__}"
removal_date = args[0]
if isinstance(removal_date, str):
removal_date = datetime.datetime.strptime(removal_date, r"%Y-%m-%d").date()
msg = args[1]
def innerWrapper(*args, **kwargs):
deprecated(name, removal_date, msg)
return func(*args, **kwargs)
return innerWrapper
return wrapper
elif len(args) == 3:
name = args[0].replace(")", "").replace("(", "")
removal_date = args[1]
if isinstance(removal_date, str):
removal_date = datetime.datetime.strptime(removal_date, r"%Y-%m-%d").date()
stack = "".join(format_stack()[:-1])
_deprecated(name, str(removal_date), args[2] + "\nStack follows:\n" + stack)
else:
raise ValueError("Got an invalid number of arguments.")
T = TypeVar("T", bound=Base)
class CppWeakRef(CppWeakRefBase, Generic[T]):
"""Weak reference to C++ object.
Use the get() method to return a Python object from the C++ object
if it exists.
"""
def __init__(self, base: T):
"""Create a CppWeakRef.
Parameters
----------
base : T
Object to create a CppWeakRef to.
"""
super().__init__(base)
[docs]
def __call__(self) -> T | None:
"""Return a Python object for the C++ class if it exists, or None if it does not.
Returns
-------
T | None
The Python object if the C++ object still exists. None if it does not.
"""
return cast(T, super().__call__())