| Conditions | 17 |
| Total Lines | 81 |
| Code Lines | 45 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like sopel.trigger.PreTrigger.__init__() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | # coding=utf-8 |
||
| 28 | def __init__(self, own_nick, line): |
||
| 29 | """own_nick is the bot's nick, needed to correctly parse sender. |
||
| 30 | line is the full line from the server.""" |
||
| 31 | line = line.strip('\r') |
||
| 32 | self.line = line |
||
| 33 | |||
| 34 | # Break off IRCv3 message tags, if present |
||
| 35 | self.tags = {} |
||
| 36 | if line.startswith('@'): |
||
| 37 | tagstring, line = line.split(' ', 1) |
||
| 38 | for tag in tagstring[1:].split(';'): |
||
| 39 | tag = tag.split('=', 1) |
||
| 40 | if len(tag) > 1: |
||
| 41 | self.tags[tag[0]] = tag[1] |
||
| 42 | else: |
||
| 43 | self.tags[tag[0]] = None |
||
| 44 | |||
| 45 | self.time = datetime.datetime.utcnow() |
||
| 46 | if 'time' in self.tags: |
||
| 47 | try: |
||
| 48 | self.time = datetime.datetime.strptime(self.tags['time'], '%Y-%m-%dT%H:%M:%S.%fZ') |
||
| 49 | except ValueError: |
||
| 50 | pass # Server isn't conforming to spec, ignore the server-time |
||
| 51 | |||
| 52 | # Grabs hostmask from line. |
||
| 53 | # Example: line = ':Sopel!foo@bar PRIVMSG #sopel :foobar!' |
||
| 54 | # print(hostmask) # Sopel!foo@bar |
||
| 55 | # All lines start with ":" except PING. |
||
| 56 | if line.startswith(':'): |
||
| 57 | self.hostmask, line = line[1:].split(' ', 1) |
||
| 58 | else: |
||
| 59 | self.hostmask = None |
||
| 60 | |||
| 61 | # Parses the line into a list of arguments. |
||
| 62 | # Some events like MODE don't have a secondary string argument, i.e. no ' :' inside the line. |
||
| 63 | # Example 1: line = ':nick!ident@domain PRIVMSG #sopel :foo bar!' |
||
| 64 | # print(text) # 'foo bar!' |
||
| 65 | # print(argstr) # ':nick!ident@domain PRIVMSG #sopel' |
||
| 66 | # print(args) # [':nick!ident@domain', 'PRIVMSG', '#sopel', 'foo bar!'] |
||
| 67 | # Example 2: line = 'irc.freenode.net MODE Sopel +i' |
||
| 68 | # print(text) # '+i' |
||
| 69 | # print(args) # ['irc.freenode.net', 'MODE', 'Sopel', '+i'] |
||
| 70 | if ' :' in line: |
||
| 71 | argstr, text = line.split(' :', 1) |
||
| 72 | self.args = argstr.split(' ') |
||
| 73 | self.args.append(text) |
||
| 74 | else: |
||
| 75 | self.args = line.split(' ') |
||
| 76 | self.text = self.args[-1] |
||
| 77 | |||
| 78 | self.event = self.args[0] |
||
| 79 | self.args = self.args[1:] |
||
| 80 | components = PreTrigger.component_regex.match(self.hostmask or '').groups() |
||
| 81 | self.nick, self.user, self.host = components |
||
| 82 | self.nick = tools.Identifier(self.nick) |
||
| 83 | |||
| 84 | # If we have arguments, the first one is the sender |
||
| 85 | # Unless it's a QUIT event |
||
| 86 | if self.args and self.event != 'QUIT': |
||
| 87 | target = tools.Identifier(self.args[0]) |
||
| 88 | else: |
||
| 89 | target = None |
||
| 90 | |||
| 91 | # Unless we're messaging the bot directly, in which case that second |
||
| 92 | # arg will be our bot's name. |
||
| 93 | if target and target.lower() == own_nick.lower(): |
||
| 94 | target = self.nick |
||
| 95 | self.sender = target |
||
| 96 | |||
| 97 | # Parse CTCP into a form consistent with IRCv3 intents |
||
| 98 | if self.event == 'PRIVMSG' or self.event == 'NOTICE': |
||
| 99 | intent_match = PreTrigger.intent_regex.match(self.args[-1]) |
||
| 100 | if intent_match: |
||
| 101 | intent, message = intent_match.groups() |
||
| 102 | self.tags['intent'] = intent |
||
| 103 | self.args[-1] = message or '' |
||
| 104 | |||
| 105 | # Populate account from extended-join messages |
||
| 106 | if self.event == 'JOIN' and len(self.args) == 3: |
||
| 107 | # Account is the second arg `...JOIN #Sopel account :realname` |
||
| 108 | self.tags['account'] = self.args[1] |
||
| 109 | |||
| 206 |