Metadata-Version: 2.4
Name: tether-references
Version: 0.1.0
Summary: Tether creates bidirectionally entangled object references
Author: Jeff McAdams
Author-email: Jeff McAdams <jeffmca@gmail.com>
License-Expression: CC-BY-SA-4.0
License-File: LICENSE
Classifier: Development Status :: 2 - Pre-Alpha
Requires-Python: >=3.14
Description-Content-Type: text/markdown

# Tether
Tether is a small python library for managing bidirectionally related  object references.

Thanks to Jeff Kala for coming up with the name, Tether, for this project. I suck at naming things and after a brief description, Jeff came up with the name, and I liked it, so this is now known as Tether. Jeff wins a mention here in the README for his naming cleverness. I'm just glad it came from another "Jeff".

By example, if you have two classes, class A and class B, when you call tether's create_relation() with appropriate arguments, class A and class B will have attributes (actually properties) injected to reference one or more objects of the other type.

The cardinality of the references can be either "one" or "many". If the cardinality of the reference is "many", the resulting attribute will be represented by a set-like object.

More concretely, using one of the classic examples for OOP, if you have a class Car, and a class Engine, assuming a one-to-one relation, when you create_relation() specifying Car and Engine, class Car will gain an attribute engine that will return the associated Engine object, and class Engine will gain an attribute car that will return the associated Car object.

	>>> from tether import create_relation
	>>> 
	>>> class Car:
	...     single='car'
	...     plural='cars'
	...     
	>>> class Engine:
	...     single='engine'
	...     plural='engines'
	...     
	>>> rel_car_engine = create_relation(name='car_engine', a_type=Car,	a_cardinality='one', b_type=Engine, b_cardinality='one')
	>>> car1 = Car()
	>>> engine1 = Engine()
	
	>>> print(car1.engine)
	None
	>>> print(engine1.car)
	None
	
	>>> car1.engine = engine1
	
	>>> print(car1.engine)
	<__main__.Engine object at 0x7cc87a398980>
	>>> print(engine1.car)
	<__main__.Car object at 0x7cc87a398830>
	>>> 

Let's change the Engine to EVMotor, so it makes sense to have a cardinality of "many":

	>>> from tether import create_relation
	>>> class Car:
	...     single='car'
	...     plural='cars'
	...     
	>>> class EVMotor:
	...     single='evmotor'
	...     plural='evmotors'
	...     
	>>> rel_car_evmotor = create_relation(name='car_evmotor', a_type=Car, a_cardinality='one', b_type=EVMotor, b_cardinality='many')
	>>> 
	>>> car1 = Car()
	>>> evmotor1 = EVMotor()
	>>> evmotor2 = EVMotor()
	>>> 
	>>> print(car1.evmotors)
	set()
	>>> print(evmotor1.car)
	None
	>>> print(evmotor2.car)
	None

	>>> evmotor1.car = car1
	
	>>> print(car1.evmotors)
	{<__main__.EVMotor object at 0x7d60c059c980>}
	>>> car1.evmotors.add(evmotor2)
	>>> print(car1.evmotors)
	{<__main__.EVMotor object at 0x7d60c059c980>, 	<__main__.EVMotor object at 0x7d60c06e6ad0>
	>>> evmotor2.car
	<__main__.Car object at 0x7d60c059c830>

You can see that the "many" cardinality relation behaviors (mostly) as a set (at the time of this writing, not all set methods are implemented), but the bidirectional relationship is maintained.

## Motivation
See [Motivation.md](Motivation.md)
