mirror of
				https://github.com/Mikaela/Limnoria.git
				synced 2025-11-03 17:17:23 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			189 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
====================================================================
 | 
						|
Code not following these style guidelines fastidiously is likely
 | 
						|
(*very* likely) not to be accepted into the Supybot core.
 | 
						|
====================================================================
 | 
						|
 | 
						|
Read PEP 8 (Guido's Style Guide) and know that we use almost all the
 | 
						|
same style guidelines.
 | 
						|
 | 
						|
Maximum line length is 79 characters.  78 is a safer bet, though.
 | 
						|
This is **NON-NEGOTIABLE**.  Your code will not be accepted while you
 | 
						|
are violating this guidline.
 | 
						|
 | 
						|
Identation is 4 spaces per level.  No tabs.  This also is
 | 
						|
**NON-NEGOTIABLE**.  Your code, again, will *never* be accepted while
 | 
						|
you have literal tabs in it.
 | 
						|
 | 
						|
Single quotes are used for all string literals that aren't docstrings.
 | 
						|
They're just easier to type.
 | 
						|
 | 
						|
Triple double quotes (""") are always used for docstrings.
 | 
						|
 | 
						|
Raw strings (r'' or r"") should be used for regular expressions.
 | 
						|
 | 
						|
Spaces go around all operators (except around '=' in default
 | 
						|
arguments to functions) and after all commas (unless doing so keeps a
 | 
						|
line within the 79 character limit).
 | 
						|
 | 
						|
Functions calls should look like this: "foo(bar(baz(x), y))".  They
 | 
						|
should not look like "foo (bar (baz (x), y))", or like
 | 
						|
"foo(bar(baz(x), y) )" or like anything else.  I hate extraneous
 | 
						|
spaces.
 | 
						|
 | 
						|
Class names are StudlyCaps.  Method and function names are camelCaps
 | 
						|
(StudlyCaps with an initial lowercase letter).  If variable and
 | 
						|
attribute names can maintain readability without being camelCaps,
 | 
						|
then they should be entirely in lowercase, otherwise they should also
 | 
						|
use camelCaps.  Plugin names are StudlyCaps.
 | 
						|
 | 
						|
Imports should always happen at the top of the module, one import per
 | 
						|
line (so if imports need to be added or removed later, it can be done
 | 
						|
easily).
 | 
						|
 | 
						|
Unless absolutely required by some external force, imports should be
 | 
						|
ordered by the string length of the module imported.  I just think it
 | 
						|
looks prettier.
 | 
						|
 | 
						|
A blank line should be between all consecutive method declarations in
 | 
						|
a class definition.  Two blank lines should be between all
 | 
						|
consecutive class definitions in a file.  Comments are even better
 | 
						|
than blank lines for separating classes.
 | 
						|
 | 
						|
Database filenames should generally begin with the name of the plugin
 | 
						|
and the extension should be 'db'.  plugins.DBHandler does this
 | 
						|
already.
 | 
						|
 | 
						|
Whenever creating a file descriptor or socket, keep a reference
 | 
						|
around and be sure to close it.  There should be no code like this:
 | 
						|
  s = urllib2.urlopen('url').read()
 | 
						|
Instead, do this:
 | 
						|
  fd = urllib2.urlopen('url')
 | 
						|
  try:
 | 
						|
    s = fd.read()
 | 
						|
  finally:
 | 
						|
    fd.close()
 | 
						|
This is to be sure the bot doesn't leak file descriptors.
 | 
						|
 | 
						|
All plugin files should include a docstring decsribing what the
 | 
						|
plugin does.  This docstring will be returned when the user is
 | 
						|
configuring the plugin.  All plugin classes should also include a
 | 
						|
docstring describing how to do things with the plugin; this docstring
 | 
						|
will be returned when the user requests help on a plugin name.
 | 
						|
 | 
						|
Method docstrings in classes deriving from callbacks.Privmsg should
 | 
						|
include an argument list as their first line, and after that a blank
 | 
						|
line followed by a longer description of what the command does.  The
 | 
						|
argument list is used by the 'syntax' command, and the longer
 | 
						|
description is used by the 'help' command.
 | 
						|
 | 
						|
Whenever joining more than two strings, use string interpolation, not
 | 
						|
addition:
 | 
						|
  s = x + y + z # Bad.
 | 
						|
  s = '%s%s%s' % (x, y, z) # Good.
 | 
						|
  s = ''.join([x, y, z]) # Best, but not as general.
 | 
						|
This has to do with efficiency; the intermediate string x+y is made
 | 
						|
(and thus copied) before x+y+z is made, so it's less efficient.
 | 
						|
People who use string concatenation in a for loop will be swiftly
 | 
						|
kicked in the head.
 | 
						|
 | 
						|
When writing strings that have formatting characters in them, don't
 | 
						|
use anything but %s unless you absolutely must.  In particular, %d
 | 
						|
should never be used, it's less general than %s and serves no useful
 | 
						|
purpose.  If you got the %d wrong, you'll get an exception that says,
 | 
						|
"foo instance can't be converted to an integer." But if you use %s,
 | 
						|
you'll get to see your nice little foo instance, if it doesn't
 | 
						|
convert to a string cleanly, and if it does convert cleanly, you'll
 | 
						|
get to see what you expect to see.  Basically, %d just sucks.
 | 
						|
 | 
						|
As a corrolary to the above, note that sometimes %f is used, but on
 | 
						|
when floats need to be formatted, e.g., %.2f.
 | 
						|
 | 
						|
Use the log module to its fullest; when you need to print some values
 | 
						|
to debug, use self.log.debug to do so, and leave those statements in
 | 
						|
the code (commented out) so they can later be re-enabled.  Remember
 | 
						|
that once code is buggy, it tends to have more bugs, and you'll
 | 
						|
probably need those print statements again.
 | 
						|
 | 
						|
While on the topic of logs, note that we do not use % (i.e.,
 | 
						|
str.__mod__) with logged strings; we simple pass the format
 | 
						|
parameters as additional arguments.  The reason is simple: the
 | 
						|
logging module supports it, and it's cleaner (fewer tokens/glyphs) to
 | 
						|
read.
 | 
						|
 | 
						|
While still on the topic of logs, it's also important to pick the
 | 
						|
appropriate log level for given information.
 | 
						|
  DEBUG:    Appropriate to tell a programmer *how* we're doing
 | 
						|
            something (i.e., debugging printfs, basically).  If
 | 
						|
	    you're trying to figure out why your code doesn't work,
 | 
						|
	    DEBUG is the new printf -- use that, and leave the
 | 
						|
	    statements in your code.
 | 
						|
  INFO:     Appropriate to tell a user *what* we're doing, when what
 | 
						|
            we're doing isn't important for the user to pay attention
 | 
						|
	    to.  A user who likes to keep up with things should enjoy
 | 
						|
	    watching our logging at the INFO level; it shouldn't be
 | 
						|
	    too low-level, but it should give enough information that
 | 
						|
	    it keeps him relatively interested at peak times.
 | 
						|
  WARNING:  Appropriate to tell a user when we're doing something
 | 
						|
            that he really ought to pay attention to.  Users should
 | 
						|
	    see WARNING and think, "Hmm, should I tell the Supybot
 | 
						|
	    developers about this?"  Later, he should decide not to,
 | 
						|
	    but it should give the user a moment to pause and think
 | 
						|
	    about what's actually happening with his bot.
 | 
						|
  ERROR:    Appropriate to tell a user when something has gone wrong.
 | 
						|
            Uncaught exceptions are ERRORs.  Conditions that we
 | 
						|
            absolutely want to hear about should be errors.  Things
 | 
						|
            that should *scare* the user should be errors.
 | 
						|
  CRITICAL: Not really appropriate.  I can think of no absolutely
 | 
						|
            critical issue yet encountered in Supybot; the only
 | 
						|
            possible thing I can imagine is to notify the user that
 | 
						|
            the partition on which Supybot is running has filled up.
 | 
						|
            That would be a CRITICAL condition, but it would also be
 | 
						|
            hard to log :)
 | 
						|
 | 
						|
All plugins should have test cases written for them.  Even if it
 | 
						|
doesn't actually test anything but just exists, it's good to have the
 | 
						|
test there so there's a place to add more tests later (and so we can
 | 
						|
be sure that all plugins are adequately documented; PluginTestCase
 | 
						|
checks that every command has documentation)
 | 
						|
 | 
						|
All uses of eval() that expect to get integrated in Supybot must be
 | 
						|
approved by jemfinch, no exceptions.  Chances are, it won't be
 | 
						|
accepted.  Have you looked at utils.safeEval?
 | 
						|
 | 
						|
SQL table names should be all-lowercase and include underscores to
 | 
						|
separate words.  This is because SQL itself is case-insensitive.
 | 
						|
This doesn't change, however the fact that variable/member names
 | 
						|
should be camel case.
 | 
						|
 | 
						|
SQL statements in code should put SQL words in ALL CAPS:
 | 
						|
"""SELECT quote FROM quotes ORDER BY random() LIMIT 1""".  This makes
 | 
						|
SQL significantly easier to read.
 | 
						|
 | 
						|
Common variable names:
 | 
						|
  L => an arbitrary list.
 | 
						|
  t => an arbitrary tuple.
 | 
						|
  x => an arbitrary float.
 | 
						|
  s => an arbitrary string.
 | 
						|
  f => an arbitrary function.
 | 
						|
  p => an arbitrary predicate.
 | 
						|
  i,n => an arbitrary integer.
 | 
						|
  cb => an arbitrary callback.
 | 
						|
  db => a database handle.
 | 
						|
  fd => a file-like object.
 | 
						|
  msg => an ircmsgs.IrcMsg object.
 | 
						|
  irc => an irclib.Irc object (or proxy)
 | 
						|
  nick => a string that is an IRC nick.
 | 
						|
  channel => a string that is an IRC channel.
 | 
						|
  hostmask => a string that is a user's IRC prefix.
 | 
						|
When the semantic functionality (that is, the "meaning" of a variable
 | 
						|
is obvious from context, one of these names should be used.  This
 | 
						|
just makes it easier for people reading our code to know what a
 | 
						|
variable represents without scouring the surrounding code.
 | 
						|
 | 
						|
Multiple variable assignments should always be surrounded with
 | 
						|
parentheses -- i.e., if you're using the partition function, then
 | 
						|
your assignment statement should look like
 | 
						|
(good, bad) = partition(p, L).  The parentheses make it obvious that
 | 
						|
you're doing a multiple assignment, and that's important because I
 | 
						|
hate reading code and wondering where a variable came from.
 |