[Python-modules-commits] [python-sievelib] 03/08: Import python-sievelib_0.9.2.orig.tar.gz

Michael Fladischer fladi at moszumanska.debian.org
Fri Dec 11 12:04:56 UTC 2015


This is an automated email from the git hooks/post-receive script.

fladi pushed a commit to branch master
in repository python-sievelib.

commit 48009d9c9299393548a4c70a4a983af5b4fd151a
Author: Michael Fladischer <FladischerMichael at fladi.at>
Date:   Thu Oct 22 10:51:55 2015 +0200

    Import python-sievelib_0.9.2.orig.tar.gz
---
 .travis.yml                            |  10 --
 COPYING                                |  28 +++---
 MANIFEST.in                            |   3 +-
 PKG-INFO                               | 172 +++++++++++++++++++++++++++++++++
 requirements.txt                       |   1 +
 setup.cfg                              |   5 +
 setup.py                               |   2 +-
 sievelib.egg-info/PKG-INFO             | 172 +++++++++++++++++++++++++++++++++
 sievelib.egg-info/SOURCES.txt          |  19 ++++
 sievelib.egg-info/dependency_links.txt |   1 +
 sievelib.egg-info/requires.txt         |   2 +
 sievelib.egg-info/top_level.txt        |   1 +
 sievelib/commands.py                   |  86 ++++++++++-------
 sievelib/factory.py                    |  65 ++++++++++---
 sievelib/managesieve.py                |   7 +-
 sievelib/parser.py                     |   5 +-
 sievelib/tests/files/utf8_sieve.txt    |   7 --
 sievelib/tests/test_factory.py         |  27 +++++-
 18 files changed, 522 insertions(+), 91 deletions(-)

diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 8f5e8ca..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-language: python
-python:
-  - "2.7"
-  - "3.4"
-
-install:
-  - pip install nose --use-mirrors
-  - python setup.py -q install
-
-script: nosetests
diff --git a/COPYING b/COPYING
index 0027393..268215f 100644
--- a/COPYING
+++ b/COPYING
@@ -1,13 +1,19 @@
-Copyright (c) 2011-2013, Antoine Nguyen <tonio at ngyn.org>
+Copyright (c) 2011-2015 Antoine Nguyen <tonio at ngyn.org>
 
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
 
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/MANIFEST.in b/MANIFEST.in
index 9491f80..c6b0605 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +1 @@
-include README.rst
-include COPYING
+include README.rst COPYING requirements.txt
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..8eb49ce
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,172 @@
+Metadata-Version: 1.1
+Name: sievelib
+Version: 0.9.2
+Summary: Client-side SIEVE library
+Home-page: https://github.com/tonioo/sievelib
+Author: Antoine Nguyen
+Author-email: tonio at ngyn.org
+License: MIT
+Description: sievelib
+        ========
+        
+        |travis| |latest-version| |downloads|
+        
+        Client-side Sieve and Managesieve library written in Python.
+        
+        * Sieve : An Email Filtering Language
+          (`RFC 5228 <http://tools.ietf.org/html/rfc5228>`_)
+        * ManageSieve : A Protocol for Remotely Managing Sieve Scripts
+          (`RFC 5804 <http://tools.ietf.org/html/rfc5804>`_)
+        
+        Installation
+        ------------
+        
+        To install ``sievelib`` from PyPI::
+        
+          pip install sievelib
+        
+        To install sievelib from git::
+        
+          git clone git at github.com:tonioo/sievelib.git
+          cd sievelib
+          python ./setup.py install
+        
+        Sieve tools
+        -----------
+        
+        What is supported
+        ^^^^^^^^^^^^^^^^^
+        
+        Currently, the provided parser supports most of the functionalities
+        described in the RFC. The only exception concerns section
+        *2.4.2.4. Encoding Characters Using "encoded-character"* which is not
+        supported.
+        
+        The following extensions are also supported:
+        
+        * Date and Index (`RFC 5260 <https://tools.ietf.org/html/rfc5260>`_)
+        * Vacation (`RFC 5230 <http://tools.ietf.org/html/rfc5230>`_)
+        
+        Extending the parser
+        ^^^^^^^^^^^^^^^^^^^^
+        
+        It is possible to extend the parser by adding new supported
+        commands. For example::
+        
+          import sievelib
+        
+          def MyCommand(sievelib.commands.ActionCommand):
+              args_definition = [
+                  {"name": "testtag",
+                      "type": ["tag"],
+                      "write_tag": True,
+                      "values": [":testtag"],
+                      "extra_arg": {"type": "number",
+                                    "required": False},
+                      "required": False},
+                  {"name": "recipients",
+                      "type": ["string", "stringlist"],
+                      "required": True}
+              ]
+        
+          sievelib.commands.add_commands(MyCommand)
+        
+        Basic usage
+        ^^^^^^^^^^^
+        
+        The parser can either be used from the command-line::
+        
+          $ cd sievelib
+          $ python parser.py test.sieve
+          Syntax OK
+          $
+        
+        Or can be used from a python environment (or script/module)::
+        
+          >>> from sievelib.parser import Parser
+          >>> p = Parser()
+          >>> p.parse('require ["fileinto"];')
+          True
+          >>> p.dump()
+          require (type: control)
+              ["fileinto"]
+          >>> 
+          >>> p.parse('require ["fileinto"]')
+          False
+          >>> p.error
+          'line 1: parsing error: end of script reached while semicolon expected'
+          >>>
+        
+        Simple filters creation
+        ^^^^^^^^^^^^^^^^^^^^^^^
+        
+        Some high-level classes are provided with the ``factory`` module, they
+        make the generation of Sieve rules easier::
+        
+          >>> from sievelib.factory import FiltersSet
+          >>> fs = FiltersSet("test")
+          >>> fs.addfilter("rule1",
+          ...              [("Sender", ":is", "toto at toto.com"),],
+          ...              [("fileinto", "Toto"),])
+          >>> fs.tosieve()
+          require ["fileinto"];
+          
+          # Filter: rule1
+          if anyof (header :is "Sender" "toto at toto.com") {
+              fileinto "Toto";
+          }
+          >>> 
+        
+        Additional documentation is available within source code.
+        
+        ManageSieve tools
+        -----------------
+        
+        What is supported
+        ^^^^^^^^^^^^^^^^^
+        
+        All mandatory commands are supported. The ``RENAME`` extension is
+        supported, with a simulated behaviour for server that do not support
+        it.
+        
+        For the ``AUTHENTICATE`` command, supported mechanisms are ``DIGEST-MD5``,
+        ``PLAIN`` and ``LOGIN``.
+            
+        Basic usage
+        ^^^^^^^^^^^
+        
+        The ManageSieve client is intended to be used from another python
+        application (there isn't any shell provided)::
+        
+          >>> from sievelib.managesieve import Client
+          >>> c = Client("server.example.com")
+          >>> c.connect("user", "password", starttls=False, authmech="DIGEST-MD5")
+          True
+          >>> c.listscripts()
+          ("active_script", ["script1", "script2"])
+          >>> c.setactive("script1")
+          True
+          >>> c.havespace("script3", 45)
+          True
+          >>>
+        
+        Additional documentation is available with source code.
+        
+        .. |latest-version| image:: https://pypip.in/v/sievelib/badge.png
+           :alt: Latest version on Pypi
+           :target: https://crate.io/packages/sievelib/
+        .. |downloads| image:: https://pypip.in/d/sievelib/badge.png
+           :alt: Downloads from Pypi
+           :target: https://crate.io/packages/sievelib/
+        .. |travis| image:: https://travis-ci.org/tonioo/sievelib.png?branch=master
+           :target: https://travis-ci.org/tonioo/sievelib
+        
+Keywords: sieve,managesieve,parser,client
+Platform: UNKNOWN
+Classifier: Programming Language :: Python
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: OS Independent
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Communications :: Email :: Filters
diff --git a/requirements.txt b/requirements.txt
index ffe2fce..dd68eb2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1,2 @@
+future
 six
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..861a9f5
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[egg_info]
+tag_build = 
+tag_date = 0
+tag_svn_revision = 0
+
diff --git a/setup.py b/setup.py
index 8171994..e20614b 100644
--- a/setup.py
+++ b/setup.py
@@ -54,7 +54,7 @@ setup(
     name="sievelib",
     packages=find_packages(),
     include_package_data=True,
-    version="0.8",
+    version="0.9.2",
     description="Client-side SIEVE library",
     author="Antoine Nguyen",
     author_email="tonio at ngyn.org",
diff --git a/sievelib.egg-info/PKG-INFO b/sievelib.egg-info/PKG-INFO
new file mode 100644
index 0000000..8eb49ce
--- /dev/null
+++ b/sievelib.egg-info/PKG-INFO
@@ -0,0 +1,172 @@
+Metadata-Version: 1.1
+Name: sievelib
+Version: 0.9.2
+Summary: Client-side SIEVE library
+Home-page: https://github.com/tonioo/sievelib
+Author: Antoine Nguyen
+Author-email: tonio at ngyn.org
+License: MIT
+Description: sievelib
+        ========
+        
+        |travis| |latest-version| |downloads|
+        
+        Client-side Sieve and Managesieve library written in Python.
+        
+        * Sieve : An Email Filtering Language
+          (`RFC 5228 <http://tools.ietf.org/html/rfc5228>`_)
+        * ManageSieve : A Protocol for Remotely Managing Sieve Scripts
+          (`RFC 5804 <http://tools.ietf.org/html/rfc5804>`_)
+        
+        Installation
+        ------------
+        
+        To install ``sievelib`` from PyPI::
+        
+          pip install sievelib
+        
+        To install sievelib from git::
+        
+          git clone git at github.com:tonioo/sievelib.git
+          cd sievelib
+          python ./setup.py install
+        
+        Sieve tools
+        -----------
+        
+        What is supported
+        ^^^^^^^^^^^^^^^^^
+        
+        Currently, the provided parser supports most of the functionalities
+        described in the RFC. The only exception concerns section
+        *2.4.2.4. Encoding Characters Using "encoded-character"* which is not
+        supported.
+        
+        The following extensions are also supported:
+        
+        * Date and Index (`RFC 5260 <https://tools.ietf.org/html/rfc5260>`_)
+        * Vacation (`RFC 5230 <http://tools.ietf.org/html/rfc5230>`_)
+        
+        Extending the parser
+        ^^^^^^^^^^^^^^^^^^^^
+        
+        It is possible to extend the parser by adding new supported
+        commands. For example::
+        
+          import sievelib
+        
+          def MyCommand(sievelib.commands.ActionCommand):
+              args_definition = [
+                  {"name": "testtag",
+                      "type": ["tag"],
+                      "write_tag": True,
+                      "values": [":testtag"],
+                      "extra_arg": {"type": "number",
+                                    "required": False},
+                      "required": False},
+                  {"name": "recipients",
+                      "type": ["string", "stringlist"],
+                      "required": True}
+              ]
+        
+          sievelib.commands.add_commands(MyCommand)
+        
+        Basic usage
+        ^^^^^^^^^^^
+        
+        The parser can either be used from the command-line::
+        
+          $ cd sievelib
+          $ python parser.py test.sieve
+          Syntax OK
+          $
+        
+        Or can be used from a python environment (or script/module)::
+        
+          >>> from sievelib.parser import Parser
+          >>> p = Parser()
+          >>> p.parse('require ["fileinto"];')
+          True
+          >>> p.dump()
+          require (type: control)
+              ["fileinto"]
+          >>> 
+          >>> p.parse('require ["fileinto"]')
+          False
+          >>> p.error
+          'line 1: parsing error: end of script reached while semicolon expected'
+          >>>
+        
+        Simple filters creation
+        ^^^^^^^^^^^^^^^^^^^^^^^
+        
+        Some high-level classes are provided with the ``factory`` module, they
+        make the generation of Sieve rules easier::
+        
+          >>> from sievelib.factory import FiltersSet
+          >>> fs = FiltersSet("test")
+          >>> fs.addfilter("rule1",
+          ...              [("Sender", ":is", "toto at toto.com"),],
+          ...              [("fileinto", "Toto"),])
+          >>> fs.tosieve()
+          require ["fileinto"];
+          
+          # Filter: rule1
+          if anyof (header :is "Sender" "toto at toto.com") {
+              fileinto "Toto";
+          }
+          >>> 
+        
+        Additional documentation is available within source code.
+        
+        ManageSieve tools
+        -----------------
+        
+        What is supported
+        ^^^^^^^^^^^^^^^^^
+        
+        All mandatory commands are supported. The ``RENAME`` extension is
+        supported, with a simulated behaviour for server that do not support
+        it.
+        
+        For the ``AUTHENTICATE`` command, supported mechanisms are ``DIGEST-MD5``,
+        ``PLAIN`` and ``LOGIN``.
+            
+        Basic usage
+        ^^^^^^^^^^^
+        
+        The ManageSieve client is intended to be used from another python
+        application (there isn't any shell provided)::
+        
+          >>> from sievelib.managesieve import Client
+          >>> c = Client("server.example.com")
+          >>> c.connect("user", "password", starttls=False, authmech="DIGEST-MD5")
+          True
+          >>> c.listscripts()
+          ("active_script", ["script1", "script2"])
+          >>> c.setactive("script1")
+          True
+          >>> c.havespace("script3", 45)
+          True
+          >>>
+        
+        Additional documentation is available with source code.
+        
+        .. |latest-version| image:: https://pypip.in/v/sievelib/badge.png
+           :alt: Latest version on Pypi
+           :target: https://crate.io/packages/sievelib/
+        .. |downloads| image:: https://pypip.in/d/sievelib/badge.png
+           :alt: Downloads from Pypi
+           :target: https://crate.io/packages/sievelib/
+        .. |travis| image:: https://travis-ci.org/tonioo/sievelib.png?branch=master
+           :target: https://travis-ci.org/tonioo/sievelib
+        
+Keywords: sieve,managesieve,parser,client
+Platform: UNKNOWN
+Classifier: Programming Language :: Python
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: OS Independent
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Communications :: Email :: Filters
diff --git a/sievelib.egg-info/SOURCES.txt b/sievelib.egg-info/SOURCES.txt
new file mode 100644
index 0000000..60762ce
--- /dev/null
+++ b/sievelib.egg-info/SOURCES.txt
@@ -0,0 +1,19 @@
+COPYING
+MANIFEST.in
+README.rst
+requirements.txt
+setup.py
+sievelib/__init__.py
+sievelib/commands.py
+sievelib/digest_md5.py
+sievelib/factory.py
+sievelib/managesieve.py
+sievelib/parser.py
+sievelib.egg-info/PKG-INFO
+sievelib.egg-info/SOURCES.txt
+sievelib.egg-info/dependency_links.txt
+sievelib.egg-info/requires.txt
+sievelib.egg-info/top_level.txt
+sievelib/tests/__init__.py
+sievelib/tests/test_factory.py
+sievelib/tests/test_parser.py
\ No newline at end of file
diff --git a/sievelib.egg-info/dependency_links.txt b/sievelib.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/sievelib.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/sievelib.egg-info/requires.txt b/sievelib.egg-info/requires.txt
new file mode 100644
index 0000000..dd68eb2
--- /dev/null
+++ b/sievelib.egg-info/requires.txt
@@ -0,0 +1,2 @@
+future
+six
diff --git a/sievelib.egg-info/top_level.txt b/sievelib.egg-info/top_level.txt
new file mode 100644
index 0000000..f789786
--- /dev/null
+++ b/sievelib.egg-info/top_level.txt
@@ -0,0 +1 @@
+sievelib
diff --git a/sievelib/commands.py b/sievelib/commands.py
index 5a27f05..9f8aa76 100644
--- a/sievelib/commands.py
+++ b/sievelib/commands.py
@@ -23,10 +23,13 @@ provides extra information such as:
 """
 from __future__ import unicode_literals
 
-import sys
 from collections import Iterable
+import sys
 
+from future.utils import python_2_unicode_compatible
 
+
+ at python_2_unicode_compatible
 class UnknownCommand(Exception):
     """Specific exception raised when an unknown command is encountered"""
 
@@ -37,6 +40,7 @@ class UnknownCommand(Exception):
         return "unknown command %s" % self.name
 
 
+ at python_2_unicode_compatible
 class BadArgument(Exception):
     """Specific exception raised when a bad argument is encountered"""
 
@@ -50,6 +54,7 @@ class BadArgument(Exception):
                % (self.seen, self.command, self.expected)
 
 
+ at python_2_unicode_compatible
 class BadValue(Exception):
     """Specific exception raised when a bad argument value is encountered"""
 
@@ -259,7 +264,7 @@ class Command(object):
             for arg in self.args_definition:
                 if arg["required"]:
                     self.required_args += 1
-        return (not self.curarg or not "extra_arg" in self.curarg) \
+        return (not self.curarg or "extra_arg" not in self.curarg) \
             and (self.rargs_cnt == self.required_args)
 
     def get_type(self):
@@ -279,7 +284,7 @@ class Command(object):
         :param value: the value to check
         :return: True on succes, False otherwise
         """
-        if not "values" in arg:
+        if "values" not in arg:
             return True
         return value.lower() in arg["values"]
 
@@ -316,7 +321,7 @@ class Command(object):
 
         if self.curarg is not None and "extra_arg" in self.curarg:
             if atype == self.curarg["extra_arg"]["type"]:
-                if not "values" in self.curarg["extra_arg"] \
+                if "values" not in self.curarg["extra_arg"] \
                    or avalue in self.curarg["extra_arg"]["values"]:
                     if add:
                         self.arguments[self.curarg["name"]] = avalue
@@ -375,7 +380,7 @@ class Command(object):
                 break
         if not found:
             raise KeyError(name)
-        if not name in self.arguments:
+        if name not in self.arguments:
             raise KeyError(name)
         return self.arguments[name]
 
@@ -407,7 +412,7 @@ class RequireCommand(ControlCommand):
             exts = self.arguments["capabilities"]
         for ext in exts:
             ext = ext.strip('"')
-            if not ext in RequireCommand.loaded_extensions:
+            if ext not in RequireCommand.loaded_extensions:
                 RequireCommand.loaded_extensions += [ext]
 
 
@@ -643,49 +648,56 @@ class VacationCommand(ActionCommand):
          "required": True},
     ]
 
+
 class SetCommand(ControlCommand):
+
     """currentdate command, part of the variables extension
 
     http://tools.ietf.org/html/rfc5229
     """
+
     is_extension = True
     args_definition = [
-            {"name": "startend", 
-             "type": ["string"], 
-             "required": True},
-            {"name": "date",
-             "type": ["string"],
-             "required": True}
+        {"name": "startend",
+         "type": ["string"],
+         "required": True},
+        {"name": "date",
+         "type": ["string"],
+         "required": True}
     ]
-    
+
+
 class CurrentdateCommand(ControlCommand):
+
     """currentdate command, part of the date extension
 
     http://tools.ietf.org/html/rfc5260#section-5
     """
+
     is_extension = True
     accept_children = True
     args_definition = [
-            {"name": "zone",
-             "type": ["tag"],
-             "write_tag": True,
-             "values": [":zone"],
-             "extra_arg": {"type": "string"},
-             "required": False},
-            {"name": "match-value",
-             "type": ["tag"],
-             "required": True},
-            {"name": "comparison",
-             "type": ["string"],
-             "required": True},
-            {"name": "match-against",
-             "type": ["string"],
-             "required": True},
-            {"name": "match-against-field",
-             "type": ["string"],
-             "required": True}
+        {"name": "zone",
+         "type": ["tag"],
+         "write_tag": True,
+         "values": [":zone"],
+         "extra_arg": {"type": "string"},
+         "required": False},
+        {"name": "match-value",
+         "type": ["tag"],
+         "required": True},
+        {"name": "comparison",
+         "type": ["string"],
+         "required": True},
+        {"name": "match-against",
+         "type": ["string"],
+         "required": True},
+        {"name": "match-against-field",
+         "type": ["string"],
+         "required": True}
     ]
 
+
 def add_commands(cmds):
     """
     Adds one or more commands to the module namespace.
@@ -718,10 +730,10 @@ def get_command_instance(name, parent=None, checkexists=True):
     """
 
     # Mapping between extension names and command names
-    extension_map = {'date': set([
-                       'currentdate']), 
-                     'variables': set([
-                       'set'])}
+    extension_map = {
+        'date': set(['currentdate']),
+        'variables': set(['set'])
+    }
     extname = name
     for extension in extension_map:
         if name in extension_map[extension]:
@@ -729,8 +741,8 @@ def get_command_instance(name, parent=None, checkexists=True):
             break
 
     cname = "%sCommand" % name.lower().capitalize()
-    if not cname in globals() or \
+    if cname not in globals() or \
             (checkexists and globals()[cname].is_extension and
-                 not extname in RequireCommand.loaded_extensions):
+             extname not in RequireCommand.loaded_extensions):
         raise UnknownCommand(name)
     return globals()[cname](parent)
diff --git a/sievelib/factory.py b/sievelib/factory.py
index 6d4e09b..840e990 100644
--- a/sievelib/factory.py
+++ b/sievelib/factory.py
@@ -9,22 +9,33 @@ without having to write or to know the syntax.
 Only commands (control/test/action) defined in the ``commands`` module
 are supported.
 """
+
 from __future__ import print_function, unicode_literals
 
 import sys
+
+from future.utils import python_2_unicode_compatible
 import six
+
 from sievelib.commands import (
     get_command_instance, IfCommand, RequireCommand, FalseCommand
 )
 
 
+ at python_2_unicode_compatible
 class FiltersSet(object):
-    def __init__(self, name, filter_name_pretext="# Filter: ", filter_desc_pretext="# Description: "):
+
+    """A set of filters."""
+
+    def __init__(self, name, filter_name_pretext=u"# Filter: ",
+                 filter_desc_pretext=u"# Description: "):
         """Represents a set of one or more filters
 
         :param name: the filterset's name
-        :param filter_name_pretext: the text that is used to mark a filters name (as comment preceding the filter)
-        :param filter_desc_pretext: the text that is used to mark a filters description
+        :param filter_name_pretext: the text that is used to mark a filter name
+                                    (as comment preceding the filter)
+        :param filter_desc_pretext: the text that is used to mark a filter
+                                     description
         """
         self.name = name
         self.filter_name_pretext = filter_name_pretext
@@ -65,6 +76,8 @@ class FiltersSet(object):
             name = "Unnamed rule %d" % cpt
             description = ""
             for comment in f.hash_comments:
+                if isinstance(comment, six.binary_type):
+                    comment = comment.decode("utf-8")
                 if comment.startswith(self.filter_name_pretext):
                     name = comment.replace(self.filter_name_pretext, "")
                 if comment.startswith(self.filter_desc_pretext):
@@ -81,7 +94,7 @@ class FiltersSet(object):
         :param name: the extension's name
         """
         name = name.strip('"')
-        if not name in self.requires:
+        if name not in self.requires:
             self.requires += [name]
 
     def __gen_require_command(self):
@@ -168,7 +181,8 @@ class FiltersSet(object):
                 )
             else:
                 if c[1].startswith(':not'):
-                    cmd = self.__build_condition(c, ifcontrol, c[1].replace("not", "", 1))
+                    cmd = self.__build_condition(
+                        c, ifcontrol, c[1].replace("not", "", 1))
                     not_cmd = get_command_instance("not", ifcontrol)
                     not_cmd.check_next_arg("test", cmd)
                     cmd = not_cmd
@@ -190,6 +204,12 @@ class FiltersSet(object):
             ifcontrol.addchild(action)
         return ifcontrol
 
+    def _unicode_filter_name(self, name):
+        """Convert name to unicode if necessary."""
+        return (
+            name.decode("utf-8") if isinstance(name, six.binary_type) else name
+        )
+
     def addfilter(self, name, conditions, actions, matchtype="anyof"):
         """Add a new filter to this filters set
 
@@ -199,9 +219,13 @@ class FiltersSet(object):
         :param matchtype: "anyof" or "allof"
         """
         ifcontrol = self.__create_filter(conditions, actions, matchtype)
-        self.filters += [{"name": name, "content": ifcontrol, "enabled": True}]
+        self.filters += [{
+            "name": self._unicode_filter_name(name), "content": ifcontrol,
+            "enabled": True}
+        ]
 
-    def updatefilter(self, oldname, newname, conditions, actions, matchtype="anyof"):
+    def updatefilter(
+            self, oldname, newname, conditions, actions, matchtype="anyof"):
         """Update a specific filter
 
         Instead of removing and re-creating the filter, we update the
@@ -213,6 +237,8 @@ class FiltersSet(object):
         :param actions: the list of actions
         :param matchtype: "anyof" or "allof"
         """
+        oldname = self._unicode_filter_name(oldname)
+        newname = self._unicode_filter_name(newname)
         for f in self.filters:
             if f["name"] == oldname:
                 f["name"] = newname
@@ -223,7 +249,8 @@ class FiltersSet(object):
                 return True
         return False
 
-    def replacefilter(self, oldname, sieve_filter, newname=None, description=None):
+    def replacefilter(
+            self, oldname, sieve_filter, newname=None, description=None):
         """replace a specific sieve_filter
 
         Instead of removing and re-creating the sieve_filter, we update the
@@ -231,8 +258,11 @@ class FiltersSet(object):
 
         :param oldname: the sieve_filter's current name
         :param newname: the sieve_filter's new name
-        :param sieve_filter: the sieve_filter object as get from FiltersSet.getfilter()
+        :param sieve_filter: the sieve_filter object as get from
+                             FiltersSet.getfilter()
         """
+        oldname = self._unicode_filter_name(oldname)
+        newname = self._unicode_filter_name(newname)
         if newname is None:
             newname = oldname
         for f in self.filters:
@@ -252,6 +282,7 @@ class FiltersSet(object):
         :param name: the filter's name
         :return: the Command object if found, None otherwise
         """
+        name = self._unicode_filter_name(name)
         for f in self.filters:
             if f["name"] == name:
                 if not f["enabled"]:
@@ -264,6 +295,7 @@ class FiltersSet(object):
 
         :param name: the filter's name
         """
+        name = self._unicode_filter_name(name)
         for f in self.filters:
             if f["name"] == name:
                 self.filters.remove(f)
@@ -277,6 +309,7 @@ class FiltersSet(object):
 
         :param name: the filter's name
         """
+        name = self._unicode_filter_name(name)
         for f in self.filters:
             if f["name"] != name:
                 continue
@@ -292,6 +325,7 @@ class FiltersSet(object):
 
         :param name: the filter's name
         """
+        name = self._unicode_filter_name(name)
         for f in self.filters:
             if f["name"] == name:
                 return self.__isdisabled(f["content"])
@@ -306,6 +340,7 @@ class FiltersSet(object):
         :param name: the filter's name
         :return: True if filter was disabled, False otherwise
         """
+        name = self._unicode_filter_name(name)
         ifcontrol = get_command_instance("if")
         falsecmd = get_command_instance("false", ifcontrol)
         ifcontrol.check_next_arg("test", falsecmd)
@@ -324,6 +359,7 @@ class FiltersSet(object):
         :param name: the filter's name
         :param direction: string "up" or "down"
         """
+        name = self._unicode_filter_name(name)
         cpt = 0
         for f in self.filters:
             if f["name"] == name:
@@ -371,13 +407,12 @@ class FiltersSet(object):
         cmd = self.__gen_require_command()
         if cmd:
             cmd.tosieve(target=target)
-            target.write("\n")
+            target.write(u"\n")
         for f in self.filters:
-            target.write(self.filter_name_pretext + f["name"] + "\n")
-            if "description" in f and len(f["description"]):
-                target.write(
-                    self.filter_desc_pretext + f["description"] + "\n"
-                )
+            target.write("{}{}\n".format(self.filter_name_pretext, f["name"]))
+            if "description" in f and f["description"]:
+                target.write(u"{}{}\n".format(
+                    self.filter_desc_pretext, f["description"]))
             f["content"].tosieve(target=target)
 
 
diff --git a/sievelib/managesieve.py b/sievelib/managesieve.py
index 91c7246..977efe6 100644
--- a/sievelib/managesieve.py
+++ b/sievelib/managesieve.py
@@ -12,11 +12,12 @@ Implementation based on <draft-martin-managesieve-12>.
 """
 from __future__ import print_function
 
-import socket
-import re
 import base64
+import re
+import socket
 import ssl
 
+from future.utils import python_2_unicode_compatible
 import six
 
 from .digest_md5 import DigestMD5
@@ -34,6 +35,7 @@ class Error(Exception):
     pass
 
 
+ at python_2_unicode_compatible
 class Response(Exception):
     def __init__(self, code, data):
         self.code = code
@@ -43,6 +45,7 @@ class Response(Exception):
         return "%s %s" % (self.code, self.data)
 
 
+ at python_2_unicode_compatible
 class Literal(Exception):
     def __init__(self, value):
         self.value = value
diff --git a/sievelib/parser.py b/sievelib/parser.py
index 8ace41f..d75a188 100755
--- a/sievelib/parser.py
+++ b/sievelib/parser.py
@@ -14,11 +14,14 @@ import codecs
 import re
 import sys
 
+from future.utils import python_2_unicode_compatible
+
 from sievelib.commands import (
     get_command_instance, UnknownCommand, BadArgument, BadValue
 )
 
 
+ at python_2_unicode_compatible
 class ParseError(Exception):
     """Generic parsing error"""
 
@@ -376,7 +379,7 @@ class Parser(object):
                 if ttype == "bracket_comment":
                     continue
                 if self.__expected is not None:
-                    if not ttype in self.__expected:
+                    if ttype not in self.__expected:
                         if self.lexer.pos < len(text):
                             msg = "%s found while %s expected near '%s'" \
                                   % (ttype, "|".join(self.__expected), text[self.lexer.pos])
diff --git a/sievelib/tests/files/utf8_sieve.txt b/sievelib/tests/files/utf8_sieve.txt
deleted file mode 100644
index 2dcc959..0000000
--- a/sievelib/tests/files/utf8_sieve.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-require ["fileinto", "reject"];
-
-# Filter: UTF8 Test Filter äöüß 汉语/漢語 Hànyǔ
-if allof (header :contains ["Subject"] ["€ 300"]) {
-    fileinto "Spam";
-    stop;
-}
diff --git a/sievelib/tests/test_factory.py b/sievelib/tests/test_factory.py
index 2b0387c..061fa14 100644
--- a/sievelib/tests/test_factory.py
+++ b/sievelib/tests/test_factory.py
@@ -7,15 +7,16 @@ from sievelib.factory import FiltersSet
 
 
 class FactoryTestCase(unittest.TestCase):
-    
+
     def setUp(self):
         self.fs = FiltersSet("test")
 
     def test_add_header_filter(self):
         output = six.StringIO()
-        self.fs.addfilter("rule1",
-                          [('Sender', ":is", 'toto at toto.com'),],
-                          [("fileinto", 'Toto'),])
+        self.fs.addfilter(
... 37 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-sievelib.git



More information about the Python-modules-commits mailing list