Best way to abstract season/show/episode data
<p>Basically, I've written an API to www.thetvdb.com in Python. The current code can be found <a href="http://github.com/dbr/tvdb_api/tree/master/tvdb_api.py">here</a>.</p>

<p>It grabs data from the API as requested, and has to store the data somehow, and make it available by doing:</p>

<pre><code>print tvdbinstance[1][23]['episodename'] # get the name of episode 23 of season 1<br></code></pre>

<p>What is the "best" way to abstract this data within the Tvdb() class?</p>

<p>I originally used a extended Dict() that automatically created sub-dicts (so you could do <code>x[1][2][3][4] = "something"</code> without having to do <code>if x[1].has_key(2): x[1][2] = []</code> and so on)</p>

<p>Then I just stored the data by doing <code>self.data[show_id][season_number][episode_number][attribute_name] = "something"</code></p>

<p>This worked okay, but there was no easy way of checking if x[3][24] was supposed to exist or not (so I couldn't raise the season_not_found exception)</p>

<p>Currently it's using four classes. ShowContainer, Show, Season and Episode. Each one is a very basic dict, which I can easily add extra functionality in (the search() function on Show() for example). Each has a <code>__setitem__</code>, <code>__getitem_</code> and <code>has_key</code></p>

<p>This works mostly fine, I can check in Shows if it has that season in it's self.data dict, if not, raise season_not_found. Check in Season() if it has that episode and so on.</p>

<p>The problem now is it's presenting itself as a dict, but doesn't have all the functionality, and because I'm overriding the <em>_getitem_</em> and <em>_setitem_</em> functions, it's easy to accidently recursively call <em>_getitem_</em> (so I'm not sure if extending the Dict class will cause problems)</p>

<p>The other slight problem is adding data into the dict is a lot more work than the old Ddict method (which was <code>self.data[seas_no][ep_no]['attribute'] = 'something'</code>). See _setItem and _setData. It's not too bad, since it's currently only a read-only API interface (so the users of the API should only ever retrieve data, not add more), but it's hardly.. elegant..</p>

<p>I think the series-of-classes system is probably the best way, but does anyone have a better idea for storing the data? And would extending the ShowContainer/etc classes with Dict cause problems?</p>
<p>OK, what you need is <code>classobj</code> from new module. That would allow you to construct exception classes dynamically (<code>classobj</code> takes a string as an argument for the class name). </p>

<pre><code>import new
myexc=new.classobj("ExcName",(Exception,),{})
i=myexc("This is the exc msg!")
raise i
</code></pre>

<p>this gives you:</p>

<pre><code>Traceback (most recent call last):
File "&lt;stdin&gt;", line 1, in &lt;module&gt;
__main__.ExcName: This is the exc msg!
</code></pre>

<p>remember that you can always get the class name through:</p>

<pre><code>self.__class__.__name__
</code></pre>

<p>So, after some string mangling and concatenation, you should be able to obtain appropriate exception class name and construct a class object using that name and then raise that exception.</p>

<p>P.S. - you can also raise strings, but this is deprecated.</p>

<pre><code>raise(self.__class__.__name__+"Exception")
</code></pre>
