I have the following Filer
entity (in the domain-driven design sense).
from dataclasses import dataclass, field
@dataclass
class Address:
street: str
city: str
state: str
zipcode: str
@dataclass
class Filer:
cik: int
name: str = field(hash=False, compare=True)
state: str = field(hash=False, compare=True)
yearend: str = field(hash=False, compare=True)
businessaddress: Address = field(hash=False, compare=True)
mailingaddress: Address = field(hash=False, compare=True)
sic: int = field(hash=False, compare=True)
ein: str = field(hash=False, compare=True, default=None)
For any Filer
, cik
by itself determines identity. I would, however, like to use equality comparisons to see if any other details about the Filer
may have changed (e.g. vs. a prior version of the same Filer
). On that basis, I set hash=False, compare=True
on all fields except cik
(for which hash=True
, by default).
The following testcase gives a quick overview of the intended behavior:
- Identity: fully determined by
cik
and tested viaAssertIs
andAssertIsNot
- Equality: determined by all fields and tested via
AssertEqual
andAssertNotEqual
import unittest
class TestFiler(unittest.TestCase):
def test_equality_same_filer(self,):
a = Filer(1234, "Some company", "Some state", "0930",
Address("Some address", "Some city", "AB", "12345"),
Address("Some address", "Some city", "AB", "12345"),
1000,
1234567)
b = Filer(1234, "Some company", "Some state", "0930",
Address("Some address", "Some city", "AB", "12345"),
Address("Some address", "Some city", "AB", "12345"),
1000,
1234567)
self.assertEqual(a, b)
def test_identity_same_filer(self,):
a = Filer(1234, "Some company", "Some state", "0930",
Address("Some address", "Some city", "AB", "12345"),
Address("Some address", "Some city", "AB", "12345"),
1000,
1234567)
b = Filer(1234, "Some company", "Some state", "0930",
Address("Some address", "Some city", "AB", "12345"),
Address("Some address", "Some city", "AB", "12345"),
1000,
1234567)
self.assertIs(a, b)
def test_equality_same_filer_new_name(self,):
a = Filer(1234, "Some company", "Some state", "0930",
Address("Some address", "Some city", "AB", "12345"),
Address("Some address", "Some city", "AB", "12345"),
1000,
1234567)
b = Filer(1234, "A new name for the company", "Some state", "0930",
Address("Some address", "Some city", "AB", "12345"),
Address("Some address", "Some city", "AB", "12345"),
1000,
1234567)
self.assertNotEqual(a, b)
def test_identity_same_filer_new_name(self,):
a = Filer(1234, "Some company", "Some state", "0930",
Address("Some address", "Some city", "AB", "12345"),
Address("Some address", "Some city", "AB", "12345"),
1000,
1234567)
b = Filer(1234, "A new name for the company", "Some state", "0930",
Address("Some address", "Some city", "AB", "12345"),
Address("Some address", "Some city", "AB", "12345"),
1000,
1234567)
self.assertIs(a, b)
def test_equality_different_filer_same_details(self,):
a = Filer(4321, "Some company", "Some state", "0930",
Address("Some address", "Some city", "AB", "12345"),
Address("Some address", "Some city", "AB", "12345"),
1000,
1234567)
b = Filer(1234, "Some company", "Some state", "0930",
Address("Some address", "Some city", "AB", "12345"),
Address("Some address", "Some city", "AB", "12345"),
1000,
1234567)
self.assertNotEqual(a, b)
def test_identity_different_filer_same_details(self,):
a = Filer(4321, "Some company", "Some state", "0930",
Address("Some address", "Some city", "AB", "12345"),
Address("Some address", "Some city", "AB", "12345"),
1000,
1234567)
b = Filer(1234, "Some company", "Some state", "0930",
Address("Some address", "Some city", "AB", "12345"),
Address("Some address", "Some city", "AB", "12345"),
1000,
1234567)
self.assertIsNot(a, b)
if __name__ == "__main__":
unittest.main()
The results didn't go as intended.
base) randm@pearljam /home/randm/Projects/secfilings $ /home/randm/Libraries/anaconda3/bin/python /home/randm/Projects/scrap/filer.py
....FF
======================================================================
FAIL: test_identity_same_filer (__main__.TestFiler)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/randm/Projects/scrap/filer.py", line 51, in test_identity_same_filer
self.assertIs(a, b)
AssertionError: Filer(cik=1234, name='Some company', state='Some state', yearend='0930', businessaddress=Address(street='Some address', city='Some city', state='AB', zipcode='12345'), mailingaddress=Address(street='Some address', city='Some city', state='AB', zipcode='12345'), sic=1000, ein=1234567) is not Filer(cik=1234, name='Some company', state='Some state', yearend='0930', businessaddress=Address(street='Some address', city='Some city', state='AB', zipcode='12345'), mailingaddress=Address(street='Some address', city='Some city', state='AB', zipcode='12345'), sic=1000, ein=1234567)
======================================================================
FAIL: test_identity_same_filer_new_name (__main__.TestFiler)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/randm/Projects/scrap/filer.py", line 77, in test_identity_same_filer_new_name
self.assertIs(a, b)
AssertionError: Filer(cik=1234, name='Some company', state='Some state', yearend='0930', businessaddress=Address(street='Some address', city='Some city', state='AB', zipcode='12345'), mailingaddress=Address(street='Some address', city='Some city', state='AB', zipcode='12345'), sic=1000, ein=1234567) is not Filer(cik=1234, name='A new name for the company', state='Some state', yearend='0930', businessaddress=Address(street='Some address', city='Some city', state='AB', zipcode='12345'), mailingaddress=Address(street='Some address', city='Some city', state='AB', zipcode='12345'), sic=1000, ein=1234567)
----------------------------------------------------------------------
Ran 6 tests in 0.001s
FAILED (failures=2)
Is there a way for me to use is
identity tests (without resorting to a dataclass method is_
or something like that, which would change the clean syntax I'm looking for in client code). Or am I simply misusing identity (which I believe is based on pointer values in CPython) and should instead be using hash equality explicitly in my client code?