[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