Skip to content
This repository has been archived by the owner on Apr 16, 2019. It is now read-only.

HierarchicalCache obscures true errors in controllers/filter tracebacks #45

Closed
EnigmaCurry opened this issue Oct 4, 2010 · 4 comments
Closed

Comments

@EnigmaCurry
Copy link
Owner

HierarchicalCache objects are designed to create sub-Caches as needed on the fly. For instance:

bf.config.one.two.three = "something"

one, two and three don't need to exist beforehand, they are created on the fly. This makes configuration less verbose and more expressive.

But when the "one" module is non-existant, the traceback is unhelpful in debugging:

>>> bf.config.controllers.one.two.three.some_method()

File "XXX", line XX, in some_method
  bf.config.controllers.one.two.three.some_method()
TypeError: 'HierarchicalCache' object is not callable

The proper traceback should emit an AttributeError on the non-existance of the "one" module. Instead, "one","two", "three" and "some_method" are created as brand new HierarchicalCache objects. Consider the effect on a developer's psyche if he misspelled the "two" module and got the above traceback? Not very helpful.

Ideally, HierarchicalCache objects would only automatically create the sub-Cache objects when the user is doing an assignment operation, rather than when calling a method or performing a slice etc.

Possible solutions:

  • Only enable the auto-creation of sub-Cache objects in the _config.py. This seems cludgy, I'd like it to work everywhere.
@EnigmaCurry
Copy link
Owner Author

To clarify the potential solution I'm thinking about:

HierarchicalCache objects would have a new attribute "automatic_building" which would be set to True upon instantiation. After all of the _config.py (and any children scripts it executes) is done executing, "bf" and all of it's children get "automatic_building = False" and this interrupts the behaviour defined in HierarchicalCache.getattr and HierarchicalCache.getitem and instead would call the super class method of the regular Cache object.

@EnigmaCurry
Copy link
Owner Author

Resolved in IRC with mpirnat:

Implement call and slice such that it detects when an attribute is uncallable or unsliceable, and find the highest parent HierarchicalCache object that was most likely to have been mistakenly typed or mistakenly missing and raise an Exception:

So assuming bf.config.blahg.some_section.some_method() is uncallable and some_section is empty and blahg is empty (other than containing some_section) we'd raise "HierarchicalCacheError: some_method not callable, 'blahg' may be an empty cache"

This will require each HierarchicalCache object to keep track of it's parent in order to traceback up the tree: c=HierarchicalCache(); c.parent=self

@mpirnat
Copy link
Contributor

mpirnat commented Oct 5, 2010

I've attempted a solution here:

http://github.com/mpirnat/blogofile/commit/c6540bfd33cb12432e6743501e4d9df366f745df

Example output (really should have unit tests but tonight was all experimentation):

>>> from blogofile.cache import HierarchicalCache
>>> x = HierarchicalCache()
>>> x.foo.bar.baz()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mpirnat/Documents/code/python/blogofile/blogofile.git/blogofile/cache.py", line 102, in __call__
    ".".join([x._key for x in hierarchy[:-1]])))
TypeError: 'HierarchicalCache' object 'baz' is not callable; 'foo.bar' may be an empty cache
>>> x.foo.bar.baz[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mpirnat/Documents/code/python/blogofile/blogofile.git/blogofile/cache.py", line 73, in __getitem__
    ".".join([x._key for x in hierarchy[:-1]])))
TypeError: 'HierarchicalCache' object 'baz' is not indexable or sliceable; 'foo.bar' may be an empty cache
>>> x.foo.bar.baz[:]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mpirnat/Documents/code/python/blogofile/blogofile.git/blogofile/cache.py", line 73, in __getitem__
    ".".join([x._key for x in hierarchy[:-1]])))
TypeError: 'HierarchicalCache' object 'baz' is not indexable or sliceable; 'foo.bar' may be an empty cache
>>> x.foo.bar.baz[1:-1]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mpirnat/Documents/code/python/blogofile/blogofile.git/blogofile/cache.py", line 73, in __getitem__
    ".".join([x._key for x in hierarchy[:-1]])))
TypeError: 'HierarchicalCache' object 'baz' is not indexable or sliceable; 'foo.bar' may be an empty cache

@mpirnat
Copy link
Contributor

mpirnat commented Oct 5, 2010

FWIW for the "X may be an empty cache", I originally attempted to indicate only the sub-tree that contained only single children, but that falls down when you do something like this (glossing over non-important things):

>>> x = HierarchicalCache()
>>> x.foo.bar.baz()
TypeError: ... 'foo.bar' may be an empty cache

>>> x.foo.quux.baz()
TypeError: ... 'quux' may be an empty cache

In the above cases, foo only holds junk/empty children, but the second error won't include foo because it looks non-empty (has more than one child).

(Aside: the previous sentence seems really strange in the context of real-world parent/child relationships... I wonder what my only-child daughter would say.)

This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants