@@ -40,7 +40,7 @@ class Episode(object):
4040 ValueError if you set an attribute to an invalid value.
4141
4242 You must have filled in either :attr:`.title` or :attr:`.summary` before
43- the RSS is generated.
43+ the RSS can be generated.
4444
4545 To add an episode to a podcast::
4646
@@ -51,12 +51,12 @@ class Episode(object):
5151
5252 You may also replace the last two lines with a shortcut::
5353
54- >>> episode = p.add_episode(Episode())
54+ >>> episode = p.add_episode(podgen. Episode())
5555
5656
5757 .. seealso::
5858
59- The :doc:`Basic Usage Guide < /user/basic_usage_guide/part_2> `
59+ :doc:`/user/basic_usage_guide/part_2`
6060 A friendlier introduction to episodes.
6161 """
6262
@@ -79,19 +79,24 @@ def __init__(self, **kwargs):
7979 up to 4000 characters in length.
8080
8181 See also :py:attr:`.Episode.subtitle` and
82- :py:attr:`.Episode.long_summary`."""
82+ :py:attr:`.Episode.long_summary`.
83+
84+ :type: :obj:`str` which can be parsed as XHTML.
85+ :RSS: description"""
8386
8487 self .long_summary = None
8588 """A long (read: full) summary, which supplements the shorter
86- :attr:`~podgen.Episode.summary`.
89+ :attr:`~podgen.Episode.summary`. Like summary, this must be compatible
90+ with XHTML parsers; use :func:`podgen.htmlencode` if this isn't HTML.
8791
8892 This attribute should be seen as a full, longer variation of
8993 summary if summary exists. Even then, the long_summary should be
9094 independent from summary, in that you only need to read one of them.
9195 This means you may have to repeat the first sentences.
9296
93- If summary does not exist but this does, this is used in place of
94- summary."""
97+ :type: :obj:`str` which can be parsed as XHTML.
98+ :RSS: content:encoded or description
99+ """
95100
96101 self .__media = None
97102
@@ -101,7 +106,7 @@ def __init__(self, **kwargs):
101106 If not present, the URL of the enclosed media is used. This is usually
102107 the best way to go, **as long as the media URL doesn't change**.
103108
104- Set the id to boolean False if you don't want to associate any id to
109+ Set the id to boolean `` False`` if you don't want to associate any id to
105110 this episode.
106111
107112 It is important that an episode keeps the same ID until the end of time,
@@ -116,17 +121,28 @@ def __init__(self, **kwargs):
116121 domain which you own (for example, use something like
117122 http://example.org/podcast/episode1 if you own example.org).
118123
119- This property corresponds to the RSS GUID element."""
124+ :type: :obj:`str`, :obj:`None` to use default or :obj:`False` to leave
125+ out.
126+ :RSS: guid
127+ """
120128
121129 self .link = None
122- """The link to the full version of this episode description.
123- Remember to start the link with the scheme, e.g. https://."""
130+ """The link to the full version of this episode's :attr:`.summary`.
131+ Remember to start the link with the scheme, e.g. https://.
132+
133+ :type: :obj:`str`
134+ :RSS: link
135+ """
124136
125137 self .__publication_date = None
126138
127139 self .title = None
128140 """This episode's human-readable title.
129- Title is mandatory and should not be blank."""
141+ Title is mandatory and should not be blank.
142+
143+ :type: :obj:`str`
144+ :RSS: title
145+ """
130146
131147 # ITunes tags
132148 # http://www.apple.com/itunes/podcasts/specs.html#rss
@@ -138,20 +154,27 @@ def __init__(self, **kwargs):
138154
139155 self .__explicit = None
140156
141- self .is_closed_captioned = None
142- """Whether this podcast includes a video episode with embedded closed
143- captioning support.
157+ self .is_closed_captioned = False
158+ """Whether this podcast includes a video episode with embedded ` closed
159+ captioning`_ support. Defaults to ``False`` .
144160
145- The two values for this tag are ``True`` and
146- ``False``."""
161+ :type: :obj:`bool`
162+ :RSS: itunes:isClosedCaptioned
163+
164+ .. _closed captioning: https://en.wikipedia.org/wiki/Closed_captioning
165+ """
147166
148167 self .__position = None
149168
150169 self .subtitle = None
151170 """A short subtitle.
152171
153172 This is shown in the Description column in iTunes.
154- The subtitle displays best if it is only a few words long."""
173+ The subtitle displays best if it is only a few words long.
174+
175+ :type: :obj:`str`
176+ :RSS: itunes:subtitle
177+ """
155178
156179 # It is time to assign the keyword arguments
157180 for attribute , value in iteritems (kwargs ):
@@ -162,7 +185,13 @@ def __init__(self, **kwargs):
162185 "recognized!" % (attribute , value ))
163186
164187 def rss_entry (self ):
165- """Create a RSS item and return it."""
188+ """Create an RSS item using lxml's etree and return it.
189+
190+ This is primarily used by :class:`podgen.Podcast` when generating the
191+ podcast's RSS feed.
192+
193+ :returns: etree.Element('item')
194+ """
166195
167196 ITUNES_NS = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
168197 DUBLIN_NS = 'http://purl.org/dc/elements/1.1/'
@@ -279,8 +308,8 @@ def authors(self):
279308 """List of :class:`~podgen.Person` that contributed to this
280309 episode.
281310
282- The authors don't need to have both name and email set. The names are
283- shown under the podcast's title on iTunes .
311+ The authors don't need to have both name and email set. They're usually
312+ not displayed anywhere .
284313
285314 .. note::
286315
@@ -308,6 +337,9 @@ def authors(self):
308337 >>> # Or assign a new list (discarding earlier authors)
309338 >>> ep.authors = [Person("John Doe", "[email protected] "), 310339 ... Person("Mary Sue", "[email protected] ")] 340+
341+ :type: :obj:`list` of :class:`podgen.Person`
342+ :RSS: author or dc:creator, and itunes:author
311343 """
312344 return self .__authors
313345
@@ -322,11 +354,22 @@ def authors(self, authors):
322354
323355 @property
324356 def publication_date (self ):
325- """Set or get the time that this episode first was made public.
357+ """The time and date this episode was first published.
358+
359+ The value can be a :obj:`str`, which will be parsed and
360+ made into a :class:`datetime.datetime` object when assigned. You may
361+ also assign a :class:`datetime.datetime` object directly. In both cases,
362+ you must ensure that the value includes timezone information.
363+
364+ :type: :obj:`str` (will be converted to and stored as
365+ :class:`datetime.datetime`) or :class:`datetime.datetime`.
366+ :RSS: pubDate
367+
368+ .. note::
326369
327- The value can either be a string which will automatically be parsed or a
328- datetime.datetime object. In both cases you must ensure that the value
329- includes timezone information.
370+ Don't use the media file's modification date as the publication
371+ date, unless they're the same. It looks very odd when an episode
372+ suddenly pops up in the feed, but it claims to be several hours old!
330373 """
331374 return self .__publication_date
332375
@@ -348,13 +391,16 @@ def media(self):
348391 """Get or set the :class:`~podgen.Media` object that is attached
349392 to this episode.
350393
351- Note that if :py:attr:`.id` is not set, the enclosure's url is used as
352- the globally unique identifier. If you rely on this, you should make
353- sure the url never changes, since changing the id messes up with clients
354- (they will think this episode is new again, even if the user already
355- has listened to it). Therefore, you should only rely on this behaviour
356- if you own the domain which the episodes reside on. If you don't, then
357- you must set :py:attr:`.id` to an appropriate value manually.
394+ Note that if :py:attr:`.id` is not set, the media's URL is used as
395+ the id. If you rely on this, you should make sure the URL never changes,
396+ since changing the id messes up with clients (they will think this
397+ episode is new again, even if the user has listened to it already).
398+ Therefore, you should only rely on this behaviour if you own the domain
399+ which the episodes reside on. If you don't, then you must set
400+ :py:attr:`.id` to an appropriate value manually.
401+
402+ :type: :class:`podgen.Media`
403+ :RSS: enclosure and itunes:duration
358404 """
359405 return self .__media
360406
@@ -374,17 +420,20 @@ def media(self, media):
374420
375421 @property
376422 def withhold_from_itunes (self ):
377- """Get or set the iTunes block attribute. Use this to prevent episodes
378- from appearing in the iTunes podcast directory. Note that the episode
379- can still be found by inspecting the XML, so it is still public.
423+ """Prevent this episode from appearing in the iTunes podcast directory.
424+ Note that the episode can still be found by inspecting the XML, so it is
425+ still public.
380426
381- One use case is if you know that this episode will get you kicked
427+ One use case would be if you knew that this episode would get you kicked
382428 out from iTunes, should it make it there. In such cases, you can set
383429 withhold_from_itunes to ``True`` so this episode isn't published on
384430 iTunes, allowing you to publish it to everyone else while keeping your
385431 podcast on iTunes.
386432
387433 This attribute defaults to ``False``, of course.
434+
435+ :type: :obj:`bool`
436+ :RSS: itunes:block
388437 """
389438 return self .__withhold_from_itunes
390439
@@ -401,29 +450,35 @@ def withhold_from_itunes(self, withhold_from_itunes):
401450
402451 @property
403452 def image (self ):
404- """The podcast episode's image.
453+ """The podcast episode's image, overriding the podcast's
454+ :attr:`~.Podcast.image`.
455+
456+ This attribute specifies the absolute URL to the artwork for your
457+ podcast. iTunes prefers square images that are at least ``1400x1400``
458+ pixels.
459+
460+ iTunes supports images in JPEG and PNG formats with an RGB color space
461+ (CMYK is not supported). The URL must end in ".jpg" or ".png".
462+
463+ :type: :obj:`str`
464+ :RSS: itunes:image
465+
466+ .. note::
467+
468+ If you change an episode’s image, you should also change the file’s
469+ name; iTunes doesn't check the actual file to see if it's changed.
470+
471+ Additionally, the server hosting your cover art image must allow HTTP
472+ HEAD requests.
405473
406474 .. warning::
407475
408476 Almost no podcatchers support this. iTunes supports it only if you
409477 embed the cover in the media file (the same way you would embed
410- an album cover), and recommends you use Garageband's Enhanced
411- Podcast feature. If you don't, the podcast's image is used instead.
478+ an album cover), and recommends that you use Garageband's Enhanced
479+ Podcast feature.
412480
413- This tag specifies the artwork for your podcast.
414- iTunes prefers square .jpg images that are at least 1400x1400 pixels,
415- which is different from what is specified for the standard RSS image
416- tag. In order for a podcast to be eligible for an iTunes Store feature,
417- the accompanying image must be at least 1400x1400 pixels.
418-
419- iTunes supports images in JPEG and PNG formats with an RGB color space
420- (CMYK is not supported). The URL must end in ".jpg" or ".png".
421-
422- If you change an episode’s image, you should also change the file’s
423- name. iTunes may not change the image if it checks your feed and the
424- image URL is the same. The server hosting your cover art image must
425- allow HTTP head requests for iTunes to be able to automatically update
426- your cover art.
481+ The podcast's image is used if this isn't supported.
427482 """
428483 return self .__image
429484
@@ -444,13 +499,16 @@ def explicit(self):
444499 inappropriate for children.
445500
446501 The value of the podcast's explicit attribute is used by default, if
447- this is ``None``.
502+ this is kept as ``None``.
448503
449504 If you set this to ``True``, an "explicit" parental advisory
450505 graphic will appear in the Name column in iTunes. If the value is
451506 ``False``, the parental advisory type is considered Clean, meaning that
452507 no explicit language or adult content is included anywhere in this
453508 episode, and a "clean" graphic will appear.
509+
510+ :type: :obj:`bool`
511+ :RSS: itunes:explicit
454512 """
455513 return self .__explicit
456514
@@ -471,9 +529,14 @@ def position(self):
471529
472530 If you would like this episode to appear first, set it to ``1``.
473531 If you want it second, set it to ``2``, and so on. If multiple episodes
474- share the same position, they will be sorted by their publication date.
532+ share the same position, they will be sorted by their
533+ :attr:`publication date <.Episode.publication_date>`.
534+
535+ To remove the order from the episode, set the position back to
536+ :obj:`None`.
475537
476- To remove the order from the episode, set the position back to ``None``.
538+ :type: :obj:`int`
539+ :RSS: itunes:order
477540 """
478541 return self .__position
479542
0 commit comments