2

On line 51/52, I get the error:

Unindent does not match any outer indentation level.

I understand this has something to do with tabs and spaces.

Note I did not write this code, I found it online and plan to modify it.

Full code (also at http://pastebin.com/n7ML6Rpz)

import os
import re
import socket
import sys
import time
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Create socket
server_socket.bind(("", 9020)) #Bind server to this socket
server_socket.listen(4) #Max number of queued connections
# Welcome message
print ("TCP chat server now awaiting client connection on port 9020...")
chat_log = [] #Contains chat log
time = time.strftime('%l:%M %p %Z on %b %d, %Y') #Server start time formatted nicely
start_time = str(time) #Convert server start time to string
username = "ChatUser" #Default server username if user does not provide one
# Support ~2^x client connections, where x is the number of process forks
os.fork()
os.fork()
os.fork()
# This variable contains the help documentation for the "help" command
chatHelp = ("The chat server accepts the following commands:\n"
+ "adios Closes the program\n"
+ "connection Shows client connection info (IP, port)\n"
+ "get Returns complete chat log\n"
+ "getrange <#> <#> Get chat log entries from <#> to <#> (starts at 1)\n"
+ "help Lists valid commands\n"
+ "name: <text> Sets your username to <text>\n"
+ "test: <text> Echo data back to you <text>\n"
+ "time Shows time when server was initiated\n"
+ "push: <text> Add <text> to chat log\n"
+ "save Save chat log to file\n")
while 1:
 # Accept connection
 client_socket, address = server_socket.accept()

 # Print connection info from client for server log
 print ("Received connection from client at"), address
# Used in the connection command function (client request) below
 connection = str(address)
# Send welcome string to client
 client_socket.send("Welcome to Nigel's chat room! You are logged in as ChatUser.\n Type help for a list of valid commands.\n")
# Loop indefinitely while server running
 while 1:
    data = client_socket.recv(2048) #Receive client data into buffer
 process_data = data.lower() #Lowercase received data for processing
 print ("Data received from client>>"), process_data #Print data received from client for log reference

 # Functions for the received commands (I use the find library to reduce compatibility errors with other languages)
 # ---"adios" command function---
if (process_data.find("adios") == 0):
     client_socket.close() #Close socket connection
 print ("<Ctrl+C to exit.>>")
 break;

 # ---"connection:" command function---
elif(process_data.find("connection") == 0):
 client_socket.send("Client connection info: " + connection + "\n")
 print "User requested connection information"

 # ---"getrange" command function w/ regular expression filtering (must be BEFORE "get" command function)---
 elif(re.match(r'getrange\s+(\d+)\s+(\d+)',process_data)): # Regex to find correct match with dynamic numbers input
 match = re.match(r'getrange\s+(\d+)\s+(\d+)',process_data)
 getValue = "Chat log from range "+ match.group(1) + " and " + match.group(2) + ":\n" # Grab first and second range number provided by client
 if(len(chat_log) >= int(match.group(1)) and len(chat_log) >= int(match.group(2))): # Check to see if chat log extends to given range
 count = int(match.group(1)) - 1
 while(count < int(match.group(2))):
 getValue += chat_log[count] + "\n"
 count += 1
 else:
 getValue += "<>\n" #No data in range provided by client
 client_socket.send(getValue) #Send results to client
# ---"get" command function---
 elif(process_data.find("get") == 0):
 log = "Chat log: \n"
 for item in chat_log:
 log += item+" \n"
 client_socket.send(log)

 # ---"help:" command function---
 elif(process_data.find("help") == 0):
 client_socket.send(chatHelp + "\n")
 print "User requested help"

 # ---"name:" command function---
 elif(process_data.find("name:") == 0):
 username = data[5:].strip() #Only grab the value client set (not "name:")
 client_socket.send("Username set to: " + data[5:] + "\n")

 # ---"test:" command function---
 elif(process_data.find("test:") == 0):
 client_socket.send(data[5:]+"\n") #Echo last 5 elements to client
 print data

 # ---"time" command function---
 elif(process_data.find("time") == 0):
 client_socket.send("Chat server was started at: " + start_time + "\n")
 print "User requested server start time"

 # ---"save" command function---
 elif(process_data.find("save") == 0):
 print "(Saving chat log to file)"
 client_socket.send("Saving chat log to file..." + "\n")
 filename = "chat.log"
 file = open(filename,"w") #Create file
 for item in chat_log: #Loop through elements in chat_log
 file.write("%s\n" % item) #Write elements one by one on a new line
 file.close() #Close/write file

 # ---"push" command function---
 elif(process_data.find("push:") == 0):
 print "(Pushing data to chat log)"
 if(username != ""):
 chat_log.append(username + ": " + data[5:].strip()) #Save actual chat text to log (not "push:")
 else:
 chat_log.append(data[5:].strip())
 client_socket.send("OK\n")
 else:
 print "<<Unknown Data Received>>",data #Server log
 try:
 client_socket.send("Unrecognized command: " + data + "") #Advise client of invalid command
 except socket.error, e:
 print "<<Ctrl+C to exit>>" #Server log
 break;
johnsyweb
  • 136,902
  • 23
  • 188
  • 247
user1543452
  • 29
  • 1
  • 2
  • Hopefully I have understood your question properly. I am pretty suspicious of the way your code in pastebin is presented, as there should be a lot more indentation than what it's showing. – Greg Hewgill Jul 22 '12 at 02:46
  • 1
    Unrelated to your question, but what did you imagine that `fork();fork();fork()` was going to do? – Kirk Strauser Jul 22 '12 at 02:58
  • I've edited the question to provide the code so the community doesn't have to look for it and also included a link to the original. – johnsyweb Jul 22 '12 at 03:02

2 Answers2

4

Python code is sensitive to the indent level you use. Your code reads:

if (process_data.find("adios") == 0):
     client_socket.close() #Close socket connection
 print ("<Ctrl+C to exit.>>")
 break;

Inside the if block, the statements must all line up. Notice how client_socket.close() and the following print statement have different indent levels. You need to change this so that they both have the same indent, like this:

if (process_data.find("adios") == 0):
 client_socket.close() #Close socket connection
 print ("<Ctrl+C to exit.>>")
 break;
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • same line. I'll fix as i go along. As i said,it's not my code,i picked it up and it's pretty buggy. I'm going to modify it. – user1543452 Jul 22 '12 at 02:52
  • I suspect the code came from http://lightloch.com/2012/03/15/simple-python-chat-client-server/ . It looks pretty poorly indented (and has semicolons on the end of lines) there, too! – johnsyweb Jul 22 '12 at 02:59
  • You're right,Johnsyweb. I've looked around for many..basic..chat clients/server. All of them seem to have errors!! – user1543452 Jul 22 '12 at 03:00
  • Ah, Wordpress. That explains the complete botching of the indentation (not your fault, obviously). – Greg Hewgill Jul 22 '12 at 03:02
  • Do you know of any..decent yet basic chat client/servers i can construct on? :) – user1543452 Jul 22 '12 at 03:03
  • Are you interested in using an existing protocol such as IRC? There are probably a zillion tutorials on how to write an IRC client in Python. Also, the first hit on Google for "python chat client" leads to this: http://code.activestate.com/recipes/531824-chat-server-client-using-selectselect/ which looks like a fine starting point. – Greg Hewgill Jul 22 '12 at 03:06
  • Wow,i'm a idiot. I never actually googled 'Python chat client' but 'python chat client AND SERVER'. Thanks! – user1543452 Jul 22 '12 at 03:10
4

The code presently reads:

if (process_data.find("adios") == 0):
     client_socket.close() #Close socket connection
 print ("<Ctrl+C to exit.>>")
 break;

The first statement in the body of the if is indented 6 spaces, while the last two statements are only indented by 1 space. The indentation level ought to be same and consistent throughout the program, something like this:

if (process_data.find("adios") == 0):
   client_socket.close() #Close socket connection
   print ("<Ctrl+C to exit.>>")
   break;

The indentation in the code doesn't seem very standard (or consistent). For instance the body of the while loop in 41/42 is indented more than other bodies of similar statements, e.g., lines 31-33, that's trouble in a language like Python where whitespace matters.

Finally, note it's not a good idea to mix tabs and spaces. PEP 8 -- Style Guide for Python Code recommends the use of spaces over tabs and an indentation of 4 spaces per level.

Levon
  • 138,105
  • 33
  • 200
  • 191