Render done need to clean expression
This commit is contained in:
		| @@ -8,6 +8,7 @@ class Expression(object): | |||||||
|     """A calculus expression. Today it can andle only expression with numbers later it will be able to manipulate unknown""" |     """A calculus expression. Today it can andle only expression with numbers later it will be able to manipulate unknown""" | ||||||
|  |  | ||||||
|     PRIORITY = {"*" : 3, "/": 3, "+": 2, "-":2, "(": 1} |     PRIORITY = {"*" : 3, "/": 3, "+": 2, "-":2, "(": 1} | ||||||
|  |     TEXSYM = {"*" : " \\times ", "+" : " + " , "-" : " - "} | ||||||
|  |  | ||||||
|     def __init__(self, exp): |     def __init__(self, exp): | ||||||
|         """ Initiate the expression |         """ Initiate the expression | ||||||
| @@ -191,11 +192,60 @@ class Expression(object): | |||||||
|     def postfix_tokens(self, val): |     def postfix_tokens(self, val): | ||||||
|         self._postfix_tokens = val |         self._postfix_tokens = val | ||||||
|  |  | ||||||
|  |     # ---------------------- | ||||||
|  |     # Latex render | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def texRender(cls, postfix_tokens): | ||||||
|  |         """@todo: Docstring for texRender | ||||||
|  |  | ||||||
|  |         :param postfix_tokens: the postfix list of tokens to transform into infix form. | ||||||
|  |         :returns: the latex render ready to insert into a maht environment | ||||||
|  |  | ||||||
|  |         >>> Expression.post2in_fix([2, 5, '+', 1, '-', 3, 4, '*', '/']) | ||||||
|  |         ['( ', 2, '+', 5, '-', 1, ' )', '/', '( ', 3, '*', 4, ' )'] | ||||||
|  |         "\frac{2 + 5 - 1}{3 \times 4)"  | ||||||
|  |         >>> Expression.post2in_fix([2]) | ||||||
|  |         "2" | ||||||
|  |         """ | ||||||
|  |         operandeStack = Stack() | ||||||
|  |          | ||||||
|  |         for token in postfix_tokens: | ||||||
|  |             if cls.isOperator(token): | ||||||
|  |                 op2 = operandeStack.pop() | ||||||
|  |                 op1 = operandeStack.pop() | ||||||
|  |  | ||||||
|  |                 if token == "/": | ||||||
|  |                     res = "\\frac{" + str(op1) + "}{" + str(op2) + "}" | ||||||
|  |  | ||||||
|  |                 else: | ||||||
|  |                     if cls.needPar(op2, token, "after"): | ||||||
|  |                         op2 = "\\left( " +  str(op2) + " \\right) " | ||||||
|  |                      | ||||||
|  |                     if cls.needPar(op1, token, "before"): | ||||||
|  |                         op2 = "\\left( " +  str(op1) + " \\right) " | ||||||
|  |                     res = str(op1) + cls.TEXSYM[token] + str(op2) | ||||||
|  |  | ||||||
|  |                 operandeStack.push(res) | ||||||
|  |  | ||||||
|  |             else: | ||||||
|  |                 operandeStack.push(token) | ||||||
|  |              | ||||||
|  |         # Manip pour gerer les cas similaires au deuxième exemple | ||||||
|  |         infix_tokens = operandeStack.pop() | ||||||
|  |         if type(infix_tokens) == list: | ||||||
|  |             infix_tokens = flatten_list(infix_tokens) | ||||||
|  |         elif cls.isNumber(infix_tokens): | ||||||
|  |             infix_tokens = [infix_tokens] | ||||||
|  |  | ||||||
|  |         return infix_tokens | ||||||
|  |  | ||||||
|  |  | ||||||
|     # ---------------------- |     # ---------------------- | ||||||
|     # "fix" tranformations |     # "fix" tranformations | ||||||
|  |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def in2post_fix(self, infix_tokens): |     def in2post_fix(cls, infix_tokens): | ||||||
|         """ From the infix_tokens list compute the corresponding postfix_tokens list |         """ From the infix_tokens list compute the corresponding postfix_tokens list | ||||||
|          |          | ||||||
|         @param infix_tokens: the infix list of tokens to transform into postfix form. |         @param infix_tokens: the infix list of tokens to transform into postfix form. | ||||||
| @@ -215,9 +265,9 @@ class Expression(object): | |||||||
|                 while topToken != "(": |                 while topToken != "(": | ||||||
|                     postfixList.append(topToken) |                     postfixList.append(topToken) | ||||||
|                     topToken = opStack.pop() |                     topToken = opStack.pop() | ||||||
|             elif self.isOperator(token): |             elif cls.isOperator(token): | ||||||
|                 # On doit ajouter la condition == str sinon python ne veut pas tester l'appartenance à la chaine de caractère.  |                 # On doit ajouter la condition == str sinon python ne veut pas tester l'appartenance à la chaine de caractère.  | ||||||
|                 while (not opStack.isEmpty()) and (self.PRIORITY[opStack.peek()] >= self.PRIORITY[token]): |                 while (not opStack.isEmpty()) and (cls.PRIORITY[opStack.peek()] >= cls.PRIORITY[token]): | ||||||
|                     postfixList.append(opStack.pop()) |                     postfixList.append(opStack.pop()) | ||||||
|                 opStack.push(token) |                 opStack.push(token) | ||||||
|             else: |             else: | ||||||
| @@ -229,7 +279,7 @@ class Expression(object): | |||||||
|         return postfixList |         return postfixList | ||||||
|  |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def post2in_fix(self, postfix_tokens): |     def post2in_fix(cls, postfix_tokens): | ||||||
|         """ From the postfix_tokens list compute the corresponding infix_tokens list |         """ From the postfix_tokens list compute the corresponding infix_tokens list | ||||||
|          |          | ||||||
|         @param postfix_tokens: the postfix list of tokens to transform into infix form. |         @param postfix_tokens: the postfix list of tokens to transform into infix form. | ||||||
| @@ -243,14 +293,14 @@ class Expression(object): | |||||||
|         operandeStack = Stack() |         operandeStack = Stack() | ||||||
|          |          | ||||||
|         for token in postfix_tokens: |         for token in postfix_tokens: | ||||||
|             if self.isOperator(token): |             if cls.isOperator(token): | ||||||
|                 op2 = operandeStack.pop() |                 op2 = operandeStack.pop() | ||||||
|                  |                  | ||||||
|                 if self.needPar(op2, token, "after"): |                 if cls.needPar(op2, token, "after"): | ||||||
|                     op2 = ["( ", op2, " )"] |                     op2 = ["( ", op2, " )"] | ||||||
|                 op1 = operandeStack.pop() |                 op1 = operandeStack.pop() | ||||||
|                  |                  | ||||||
|                 if self.needPar(op1, token, "before"): |                 if cls.needPar(op1, token, "before"): | ||||||
|                     op1 = ["( ", op1, " )"] |                     op1 = ["( ", op1, " )"] | ||||||
|                 res = [op1, token, op2] |                 res = [op1, token, op2] | ||||||
|  |  | ||||||
| @@ -263,7 +313,7 @@ class Expression(object): | |||||||
|         infix_tokens = operandeStack.pop() |         infix_tokens = operandeStack.pop() | ||||||
|         if type(infix_tokens) == list: |         if type(infix_tokens) == list: | ||||||
|             infix_tokens = flatten_list(infix_tokens) |             infix_tokens = flatten_list(infix_tokens) | ||||||
|         elif self.isNumber(infix_tokens): |         elif cls.isNumber(infix_tokens): | ||||||
|             infix_tokens = [infix_tokens] |             infix_tokens = [infix_tokens] | ||||||
|  |  | ||||||
|         return infix_tokens |         return infix_tokens | ||||||
| @@ -272,7 +322,7 @@ class Expression(object): | |||||||
|     # Tools for placing parenthesis in infix notation |     # Tools for placing parenthesis in infix notation | ||||||
|  |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def needPar(self, operande, operator, posi = "after"): |     def needPar(cls, operande, operator, posi = "after"): | ||||||
|         """Says whether or not the operande needs parenthesis |         """Says whether or not the operande needs parenthesis | ||||||
|  |  | ||||||
|         :param operande: the operande |         :param operande: the operande | ||||||
| @@ -280,13 +330,13 @@ class Expression(object): | |||||||
|         :param posi: "after"(default) if the operande will be after the operator, "before" othewise |         :param posi: "after"(default) if the operande will be after the operator, "before" othewise | ||||||
|         :returns: bollean |         :returns: bollean | ||||||
|         """ |         """ | ||||||
|         if self.isNumber(operande) and operande < 0: |         if cls.isNumber(operande) and operande < 0: | ||||||
|             return 1 |             return 1 | ||||||
|         elif not self.isNumber(operande): |         elif not cls.isNumber(operande): | ||||||
|             # Si c'est une grande expression ou un chiffre négatif |             # Si c'est une grande expression ou un chiffre négatif | ||||||
|             stand_alone = self.get_main_op(operande) |             stand_alone = cls.get_main_op(operande) | ||||||
|             # Si la priorité de l'operande est plus faible que celle de l'opérateur |             # Si la priorité de l'operande est plus faible que celle de l'opérateur | ||||||
|             minor_priority = self.PRIORITY[self.get_main_op(operande)] < self.PRIORITY[operator] |             minor_priority = cls.PRIORITY[cls.get_main_op(operande)] < cls.PRIORITY[operator] | ||||||
|             # Si l'opérateur est -/ pour after ou juste / pour before |             # Si l'opérateur est -/ pour after ou juste / pour before | ||||||
|             special = (operator in "-/" and posi == "after") or (operator in "/" and posi == "before") |             special = (operator in "-/" and posi == "after") or (operator in "/" and posi == "before") | ||||||
|  |  | ||||||
| @@ -295,13 +345,16 @@ class Expression(object): | |||||||
|             return 0 |             return 0 | ||||||
|      |      | ||||||
|     @classmethod |     @classmethod | ||||||
|     def get_main_op(self, tokens): |     def get_main_op(cls, tokens): | ||||||
|         """Getting the main operation of the list of tokens |         """Getting the main operation of the list of tokens | ||||||
|  |  | ||||||
|         :param exp: the list of tokens |         :param exp: the list of tokens | ||||||
|         :returns: the main operation (+, -, * or /) or 0 if the expression is only one element |         :returns: the main operation (+, -, * or /) or 0 if the expression is only one element | ||||||
|  |  | ||||||
|         """ |         """ | ||||||
|  |  | ||||||
|  |         print("tokens: ", tokens) | ||||||
|  |  | ||||||
|         parStack = Stack() |         parStack = Stack() | ||||||
|  |  | ||||||
|         if len(tokens) == 1: |         if len(tokens) == 1: | ||||||
| @@ -315,10 +368,12 @@ class Expression(object): | |||||||
|                 parStack.push(token) |                 parStack.push(token) | ||||||
|             elif token == ")": |             elif token == ")": | ||||||
|                 parStack.pop() |                 parStack.pop() | ||||||
|             elif self.isOperator(token) and parStack.isEmpty(): |             elif cls.isOperator(token) and parStack.isEmpty(): | ||||||
|                 main_op.append(token) |                 main_op.append(token) | ||||||
|  |  | ||||||
|         return min(main_op, key = lambda s: self.PRIORITY[s]) |         print("main_op", main_op) | ||||||
|  |  | ||||||
|  |         return min(main_op, key = lambda s: cls.PRIORITY[s]) | ||||||
|  |  | ||||||
|     ## --------------------- |     ## --------------------- | ||||||
|     ## Computing the expression |     ## Computing the expression | ||||||
| @@ -368,7 +423,7 @@ class Expression(object): | |||||||
| def test(exp): | def test(exp): | ||||||
|     a = Expression(exp) |     a = Expression(exp) | ||||||
|     #for i in a.simplify(): |     #for i in a.simplify(): | ||||||
|     for i in a.simplify(render = render): |     for i in a.simplify(render = Expression.texRender): | ||||||
|         print(i) |         print(i) | ||||||
|  |  | ||||||
|     print("\n") |     print("\n") | ||||||
|   | |||||||
							
								
								
									
										184
									
								
								render.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								render.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,184 @@ | |||||||
|  | #!/usr/bin/env python | ||||||
|  | # encoding: utf-8 | ||||||
|  |  | ||||||
|  | from generic import Stack,flatten_list | ||||||
|  | from fraction import Fraction | ||||||
|  |  | ||||||
|  |          | ||||||
|  |  | ||||||
|  | class Render(object): | ||||||
|  |     """A class which aims to create render functions from three dictionnaries: | ||||||
|  |         - op_infix: dict of caracters | ||||||
|  |         - op_postfix: dict of 2 arguments functions | ||||||
|  |         - other: dict of caracters | ||||||
|  |     Those three dictionnaries while define how a postfix expression will be transform into a string. | ||||||
|  |     """ | ||||||
|  |  | ||||||
|  |     PRIORITY = {"*" : 3, "/": 3, "+": 2, "-":2, "(": 1} | ||||||
|  |  | ||||||
|  |     def __init__(self, op_infix = {}, op_postfix = {}, other = {}): | ||||||
|  |         """Initiate the render | ||||||
|  |          | ||||||
|  |         @param op_infix: the dictionnary of infix operator with how they have to be render | ||||||
|  |         @param op_postfix: the dictionnary of postfix operator with how they have to be render | ||||||
|  |         @param other: other caracters like parenthesis. | ||||||
|  |         """ | ||||||
|  |  | ||||||
|  |         self.op_infix = op_infix | ||||||
|  |         self.op_postfix = op_postfix | ||||||
|  |         self.other = other | ||||||
|  |         # TODO: there may be issues with PRIORITY | ||||||
|  |  | ||||||
|  |         self.operators = list(self.op_infix.keys()) + list(self.op_postfix.keys()) + list(self.other.keys()) | ||||||
|  |  | ||||||
|  |     def __call__(self, postfix_tokens): | ||||||
|  |         """Make the object acting like a function | ||||||
|  |  | ||||||
|  |         :param postfix_tokens: the list of postfix tokens to be render | ||||||
|  |         :returns: the render string | ||||||
|  |  | ||||||
|  |         """ | ||||||
|  |         operandeStack = Stack() | ||||||
|  |  | ||||||
|  |          | ||||||
|  |         for token in postfix_tokens: | ||||||
|  |             if self.isOperator(token): | ||||||
|  |                 op2 = operandeStack.pop() | ||||||
|  |                  | ||||||
|  |                 if self.needPar(op2, token, "after"): | ||||||
|  |                     op2 = self.other["("] +  str(op2) + self.other[")"] | ||||||
|  |                 op1 = operandeStack.pop() | ||||||
|  |                  | ||||||
|  |                 if self.needPar(op1, token, "before"): | ||||||
|  |                     op1 = self.other["("] +  str(op1) + self.other[")"] | ||||||
|  |  | ||||||
|  |  | ||||||
|  |                 if token in self.op_infix: | ||||||
|  |                     res = fstr(str(op1) + self.op_infix[token] +  str(op2)) | ||||||
|  |  | ||||||
|  |                 elif token in self.op_postfix: | ||||||
|  |                     res = fstr(self.op_postfix[token](str(op1), str(op2))) | ||||||
|  |  | ||||||
|  |                 # Trick to remember the main op when the render will be done! | ||||||
|  |                 res.mainOp = token | ||||||
|  |  | ||||||
|  |                 operandeStack.push(res) | ||||||
|  |  | ||||||
|  |             else: | ||||||
|  |                 operandeStack.push(token) | ||||||
|  |              | ||||||
|  |         # Manip pour gerer les cas similaires au deuxième exemple | ||||||
|  |         infix_tokens = operandeStack.pop() | ||||||
|  |         if type(infix_tokens) == list: | ||||||
|  |             infix_tokens = flatten_list(infix_tokens) | ||||||
|  |         elif self.isNumber(infix_tokens): | ||||||
|  |             infix_tokens = [infix_tokens] | ||||||
|  |  | ||||||
|  |         return infix_tokens | ||||||
|  |  | ||||||
|  |     # --------------------- | ||||||
|  |     # Tools for placing parenthesis in infix notation | ||||||
|  |  | ||||||
|  |     def needPar(self, operande, operator, posi = "after"): | ||||||
|  |         """Says whether or not the operande needs parenthesis | ||||||
|  |  | ||||||
|  |         :param operande: the operande | ||||||
|  |         :param operator: the operator | ||||||
|  |         :param posi: "after"(default) if the operande will be after the operator, "before" othewise | ||||||
|  |         :returns: bollean | ||||||
|  |         """ | ||||||
|  |         if self.isNumber(operande) and operande < 0: | ||||||
|  |             return 1 | ||||||
|  |         elif not self.isNumber(operande): | ||||||
|  |             # Si c'est une grande expression ou un chiffre négatif | ||||||
|  |             stand_alone = self.get_main_op(operande) | ||||||
|  |             # Si la priorité de l'operande est plus faible que celle de l'opérateur | ||||||
|  |             minor_priority = self.PRIORITY[self.get_main_op(operande)] < self.PRIORITY[operator] | ||||||
|  |             # Si l'opérateur est -/ pour after ou juste / pour before | ||||||
|  |             special = (operator in "-/" and posi == "after") or (operator in "/" and posi == "before") | ||||||
|  |  | ||||||
|  |             return stand_alone and (minor_priority or special) | ||||||
|  |         else: | ||||||
|  |             return 0 | ||||||
|  |  | ||||||
|  |     def get_main_op(self, tokens): | ||||||
|  |         """Getting the main operation of the list of tokens | ||||||
|  |  | ||||||
|  |         :param exp: the list of tokens | ||||||
|  |         :returns: the main operation (+, -, * or /) or 0 if the expression is only one element | ||||||
|  |  | ||||||
|  |         """ | ||||||
|  |         if hasattr(tokens, "mainOp"): | ||||||
|  |             return tokens.mainOp | ||||||
|  |  | ||||||
|  |         if len(tokens) == 1: | ||||||
|  |             # Si l'expression n'est qu'un élément | ||||||
|  |             return 0 | ||||||
|  |  | ||||||
|  |         parStack = Stack() | ||||||
|  |         main_op = [] | ||||||
|  |  | ||||||
|  |         for token in tokens: | ||||||
|  |             if token == "(": | ||||||
|  |                 parStack.push(token) | ||||||
|  |             elif token == ")": | ||||||
|  |                 parStack.pop() | ||||||
|  |             elif self.isOperator(token) and parStack.isEmpty(): | ||||||
|  |                 main_op.append(token) | ||||||
|  |  | ||||||
|  |         return min(main_op, key = lambda s: self.PRIORITY[s]) | ||||||
|  |  | ||||||
|  |     ## --------------------- | ||||||
|  |     ## Recognize numbers and operators | ||||||
|  |  | ||||||
|  |     def isNumber(self, exp): | ||||||
|  |         """Check if the expression can be a number which means that it is not a operator | ||||||
|  |  | ||||||
|  |         :param exp: an expression | ||||||
|  |         :returns: True if the expression can be a number and false otherwise | ||||||
|  |  | ||||||
|  |         """ | ||||||
|  |         return type(exp) == int or type(exp) == Fraction | ||||||
|  |  | ||||||
|  |     def isOperator(self, exp): | ||||||
|  |         """Check if the expression is in self.operators | ||||||
|  |  | ||||||
|  |         :param exp: an expression | ||||||
|  |         :returns: boolean | ||||||
|  |  | ||||||
|  |         """ | ||||||
|  |         return (type(exp) == str and exp in self.operators) | ||||||
|  |          | ||||||
|  | class fstr(str): | ||||||
|  |     """Fake string - they are used to stock the main operation of an rendered expression""" | ||||||
|  |     pass | ||||||
|  |  | ||||||
|  | txt_infix = {"+": " + ", "-": " - ", "*": " * ", "/" : " / "} | ||||||
|  | txt_postfix = {} | ||||||
|  | txt_other = {"(": "( ", ")": ") "} | ||||||
|  | txt_render = Render(txt_infix, txt_postfix, txt_other) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def texFrac(op1, op2): | ||||||
|  |     if op1[0] == "(" and op1[-1] == ")": | ||||||
|  |         op1 = op1[1:-1] | ||||||
|  |     if op2[0] == "(" and op2[-1] == ")": | ||||||
|  |         op2 = op2[1:-1] | ||||||
|  |     return "\\frac{" + str(op1) + "}{" + str(op2) + "}" | ||||||
|  |  | ||||||
|  | tex_infix = {"+": " + ", "-": " - ", "*": " * "} | ||||||
|  | tex_postfix = {"/": texFrac} | ||||||
|  | tex_other = {"(": "( ", ")": " )"} | ||||||
|  | tex_render = Render(tex_infix, tex_postfix, tex_other) | ||||||
|  |  | ||||||
|  | if __name__ == '__main__': | ||||||
|  |     #exp = [2, 5, '+', 1, '-', 3, 4, '*', '/'] | ||||||
|  |     #print(txt_render(exp)) | ||||||
|  |     exp = [2, 5, '+', 1, '-', 3, 4, '*', '/', 3, '+'] | ||||||
|  |     print(tex_render(exp)) | ||||||
|  |      | ||||||
|  |  | ||||||
|  | # ----------------------------- | ||||||
|  | # Reglages pour 'vim' | ||||||
|  | # vim:set autoindent expandtab tabstop=4 shiftwidth=4: | ||||||
|  | # cursor: 16 del  | ||||||
							
								
								
									
										55
									
								
								texRender.py
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								texRender.py
									
									
									
									
									
								
							| @@ -1,55 +0,0 @@ | |||||||
| #!/usr/bin/env python |  | ||||||
| # encoding: utf-8 |  | ||||||
|  |  | ||||||
| from generic import Stack |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def post2in_fix(postfix_tokens): |  | ||||||
|     """ From the postfix_tokens list compute the corresponding infix_tokens list |  | ||||||
|      |  | ||||||
|     @param postfix_tokens: the postfix list of tokens to transform into infix form. If nothing is set, it takes the value self.postfix_tokens |  | ||||||
|     @return: the corresponding infix list of tokens if postfix_tokens is set. nothing otherwise but stock it in self.infix_tokens |  | ||||||
|  |  | ||||||
|     >>> post2in_fix([2, 5, '+', 1, '-', 3, 4, '*', '/']) |  | ||||||
|     ['( ', 2, '+', 5, '-', 1, ' )', '/', '( ', 3, '*', 4, ' )'] |  | ||||||
|     """ |  | ||||||
|     operandeStack = Stack() |  | ||||||
|  |  | ||||||
|     for token in postfix_tokens: |  | ||||||
|         if self.isOperator(token): |  | ||||||
|             op2 = operandeStack.pop() |  | ||||||
|             if self.needPar(op2, token, "after"): |  | ||||||
|                 op2 = ["( ", op2, " )"] |  | ||||||
|             op1 = operandeStack.pop() |  | ||||||
|             if self.needPar(op1, token, "before"): |  | ||||||
|                 op1 = ["( ", op1, " )"] |  | ||||||
|             res = [op1, token, op2] |  | ||||||
|  |  | ||||||
|             operandeStack.push(res) |  | ||||||
|  |  | ||||||
|         else: |  | ||||||
|             operandeStack.push(token) |  | ||||||
|  |  | ||||||
|     infix_tokens = flatten_list(operandeStack.pop()) |  | ||||||
|  |  | ||||||
|     return infix_tokens |  | ||||||
|  |  | ||||||
| def textRender(postfix_tokens): |  | ||||||
|     """ A text baser render |  | ||||||
|  |  | ||||||
|     :param postfix_tokens: The postfix list of tokens |  | ||||||
|     :returns: the text expression |  | ||||||
|  |  | ||||||
|     """ |  | ||||||
|     infix_tokens = post2in_fix(postfix_tokens) |  | ||||||
|     return ' '.join(infix_tokens) |  | ||||||
|  |  | ||||||
| if __name__ == '__main__': |  | ||||||
|      |  | ||||||
|     import doctest |  | ||||||
|     doctest.testmod() |  | ||||||
|  |  | ||||||
| # ----------------------------- |  | ||||||
| # Reglages pour 'vim' |  | ||||||
| # vim:set autoindent expandtab tabstop=4 shiftwidth=4: |  | ||||||
| # cursor: 16 del  |  | ||||||
		Reference in New Issue
	
	Block a user