Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
zope.proxy
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
zope.proxy
Commits
230ab48d
Commit
230ab48d
authored
Mar 01, 2006
by
Jim Fulton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
make more generic
parent
10c59e84
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
12 additions
and
860 deletions
+12
-860
INSTALL.txt
INSTALL.txt
+0
-83
setup.py
setup.py
+12
-12
src/zope/i18nmessageid/DEPENDENCIES.cfg
src/zope/i18nmessageid/DEPENDENCIES.cfg
+0
-2
src/zope/i18nmessageid/SETUP.cfg
src/zope/i18nmessageid/SETUP.cfg
+0
-3
src/zope/i18nmessageid/__init__.py
src/zope/i18nmessageid/__init__.py
+0
-38
src/zope/i18nmessageid/_zope_i18nmessageid_message.c
src/zope/i18nmessageid/_zope_i18nmessageid_message.c
+0
-266
src/zope/i18nmessageid/message.py
src/zope/i18nmessageid/message.py
+0
-188
src/zope/i18nmessageid/messageid.py
src/zope/i18nmessageid/messageid.py
+0
-114
src/zope/i18nmessageid/messages.txt
src/zope/i18nmessageid/messages.txt
+0
-125
src/zope/i18nmessageid/tests.py
src/zope/i18nmessageid/tests.py
+0
-29
No files found.
INSTALL.txt
deleted
100644 → 0
View file @
10c59e84
Installing This Package
=======================
Prerequisites
-------------
The installation steps below assume that you have the cool new 'setuptools'
package installed in your Python. Here is where to get it:
$ wget http://peak.telecommunity.com/dist/ez_setup.py
$ /path/to/your/python ez_setup.py # req. write access to 'site-packages'
- Docs for EasyInstall:
http://peak.telecommunity.com/DevCenter/EasyInstall
- Docs for setuptools:
http://peak.telecommunity.com/DevCenter/setuptools
- Docs for eggs:
http://peak.telecommunity.com/DevCenter/PythonEggs
Installing a Development Checkout
---------------------------------
Check out the package from subversion:
$ svn co svn+ssh://svn.zope.org/repos/main/zope.i18nmessageid/trunk \
src/zope.i18nmessageid
$ cd src/zope.i18nmessageid
Install it as a "devlopment egg" (which also installs its "hard"
dependencies):
$ /path/to/your/python setup.py devel
The installation of dependency eggs uses the 'setup.cfg' file in
the checkout. You can supply '--find-links' on the command line to
point it at a non-standard package repository.
Running the Tests
-----------------
To test the package, you will also need the 'zope.testing' package, which
can't (yet) be automatically installed. Eventually, you should be able to
type:
$ /path/to/your/python setup.py test
and have it install the "testing dependencies." Today, the workaround
is to install it manually:
$ /path/to/easy_install --find-links="...." zope-testing
You can then run the tests (finally) from the checkout directory:
$ /path/to/your/python test.py
Running:
.............
Ran 13 tests with 0 failures and 0 errors in 0.094 seconds.
Installing a Source Distribution
--------------------------------
You can also install it from a source distribution:
$ /path/to/easy_install --find-links="...." -eb src zope-i18nmessageid
$ cd src/zope.i18nmessageid
$ /path/to/your/python setup.py devel
Installing a Binary Egg
-----------------------
Install the package as a "binary egg" (which also installs its "hard"
dependencies):
$ /path/to/easy_install --find-links="...." zope-i18nmessageid
setup.py
View file @
230ab48d
...
...
@@ -23,28 +23,28 @@ try:
except
ImportError
,
e
:
from
distutils.core
import
setup
,
Extension
setup
(
name
=
'zope_i18nmessageid'
,
version
=
'3.0'
,
url
=
'http://svn.zope.org/zope.i18nmessageid'
,
setup
(
name
=
'zope.XXX'
,
version
=
'1.0'
,
url
=
'http://svn.zope.org/zope.XXX'
,
license
=
'ZPL 2.1'
,
description
=
'
Zope 3 i18n Message Identifier
'
,
description
=
'
XXX
'
,
author
=
'Zope Corporation and Contributors'
,
author_email
=
'zope3-dev@zope.org'
,
long_description
=
''
,
packages
=
[
'zope'
,
'zope.
i18nmessageid
'
],
package_dir
=
{
''
:
'src'
},
packages
=
[
'zope'
,
'zope.
XXX
'
],
package_dir
=
{
''
:
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'src'
)
},
ext_modules
=
[
Extension
(
"zope.i18nmessageid._zope_i18nmessageid_message
"
,
[
os
.
path
.
join
(
'src'
,
'zope'
,
'i18nmessageid
'
,
"_zope_i18nmessageid_message
.c"
)
]),
],
## ext_modules=[Extension("zope.XXX._zope_XXX
",
## [os.path.join('src', 'zope', 'XXX
',
## "_zope_XXX
.c")
##
]),
##
],
namespace_packages
=
[
'zope'
,],
tests_require
=
[
'zope_testing'
],
install_requires
=
[
'zope_deprecation'
],
devel_requires
=
[],
include_package_data
=
True
,
zip_safe
=
False
,
...
...
src/zope/i18nmessageid/DEPENDENCIES.cfg
deleted
100644 → 0
View file @
10c59e84
zope.testing
zope.deprecation
src/zope/i18nmessageid/SETUP.cfg
deleted
100644 → 0
View file @
10c59e84
<extension _zope_i18nmessageid_message>
source _zope_i18nmessageid_message.c
</extension>
src/zope/i18nmessageid/__init__.py
deleted
100644 → 0
View file @
10c59e84
##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""I18n Messages
$Id$
"""
##############################################################################
# BBB 2005/10/10 -- MessageIDs are to be removed for Zope 3.3
#
import
zope.deprecation
zope
.
deprecation
.
__show__
.
off
()
from
zope.i18nmessageid.messageid
import
MessageID
,
MessageIDFactory
zope
.
deprecation
.
__show__
.
on
()
zope
.
deprecation
.
deprecated
(
'MessageID'
,
'Mutable i18n messages ("message ids") have been '
'deprecated in favour of immutable ones and will '
'be removed in Zope 3.3. Please use '
'zope.i18nmessageid.Message instead.'
)
zope
.
deprecation
.
deprecated
(
'MessageIDFactory'
,
'Mutable i18n messages ("message ids") have been '
'deprecated in favour of immutable ones and will '
'be removed in Zope 3.3. Please use '
'use zope.i18nmessageid.MessageFactory instead.'
)
#
##############################################################################
from
zope.i18nmessageid.message
import
Message
,
MessageFactory
src/zope/i18nmessageid/_zope_i18nmessageid_message.c
deleted
100644 → 0
View file @
10c59e84
/*############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
############################################################################*/
/* $Id$ */
#include "Python.h"
/* these macros make gc support easier; they are only available in
Python 2.4 and borrowed from there */
#ifndef Py_CLEAR
#define Py_CLEAR(op) \
do { \
if (op) { \
PyObject *tmp = (op); \
(op) = NULL; \
Py_DECREF(tmp); \
} \
} while (0)
#endif
#ifndef Py_VISIT
#define Py_VISIT(op) \
do { \
if (op) { \
int vret = visit((op), arg); \
if (vret) \
return vret; \
} \
} while (0)
#endif
/* ----------------------------------------------------- */
typedef
struct
{
PyUnicodeObject
base
;
PyObject
*
domain
;
PyObject
*
default_
;
PyObject
*
mapping
;
}
Message
;
static
PyTypeObject
MessageType
;
static
PyObject
*
Message_new
(
PyTypeObject
*
type
,
PyObject
*
args
,
PyObject
*
kwds
)
{
static
char
*
kwlist
[]
=
{
"value"
,
"domain"
,
"default"
,
"mapping"
,
NULL
};
PyObject
*
value
,
*
domain
=
NULL
,
*
default_
=
NULL
,
*
mapping
=
NULL
,
*
s
;
Message
*
self
;
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwds
,
"O|OOO"
,
kwlist
,
&
value
,
&
domain
,
&
default_
,
&
mapping
))
return
NULL
;
args
=
Py_BuildValue
(
"(O)"
,
value
);
if
(
args
==
NULL
)
return
NULL
;
s
=
PyUnicode_Type
.
tp_new
(
type
,
args
,
NULL
);
Py_DECREF
(
args
);
if
(
s
==
NULL
)
return
NULL
;
if
(
!
PyObject_TypeCheck
(
s
,
&
MessageType
))
{
PyErr_SetString
(
PyExc_TypeError
,
"unicode.__new__ didn't return a Message"
);
Py_DECREF
(
s
);
return
NULL
;
}
self
=
(
Message
*
)
s
;
if
(
PyObject_TypeCheck
(
value
,
&
MessageType
))
{
self
->
domain
=
((
Message
*
)
value
)
->
domain
;
self
->
default_
=
((
Message
*
)
value
)
->
default_
;
self
->
mapping
=
((
Message
*
)
value
)
->
mapping
;
}
else
{
self
->
domain
=
self
->
default_
=
self
->
mapping
=
NULL
;
}
if
(
domain
!=
NULL
)
self
->
domain
=
domain
;
if
(
default_
!=
NULL
)
self
->
default_
=
default_
;
if
(
mapping
!=
NULL
)
self
->
mapping
=
mapping
;
Py_XINCREF
(
self
->
mapping
);
Py_XINCREF
(
self
->
default_
);
Py_XINCREF
(
self
->
domain
);
return
(
PyObject
*
)
self
;
}
/* Code to access structure members by accessing attributes */
#include "structmember.h"
static
PyMemberDef
Message_members
[]
=
{
{
"domain"
,
T_OBJECT
,
offsetof
(
Message
,
domain
),
RO
},
{
"default"
,
T_OBJECT
,
offsetof
(
Message
,
default_
),
RO
},
{
"mapping"
,
T_OBJECT
,
offsetof
(
Message
,
mapping
),
RO
},
{
NULL
}
/* Sentinel */
};
static
int
Message_traverse
(
Message
*
self
,
visitproc
visit
,
void
*
arg
)
{
Py_VISIT
(
self
->
domain
);
Py_VISIT
(
self
->
default_
);
Py_VISIT
(
self
->
mapping
);
return
0
;
}
static
int
Message_clear
(
Message
*
self
)
{
Py_CLEAR
(
self
->
domain
);
Py_CLEAR
(
self
->
default_
);
Py_CLEAR
(
self
->
mapping
);
return
0
;
}
static
void
Message_dealloc
(
Message
*
self
)
{
Message_clear
(
self
);
self
->
base
.
ob_type
->
tp_free
((
PyObject
*
)
self
);
}
static
PyObject
*
Message_reduce
(
Message
*
self
)
{
PyObject
*
value
,
*
result
;
value
=
PyObject_CallFunctionObjArgs
((
PyObject
*
)
&
PyUnicode_Type
,
self
,
NULL
);
if
(
value
==
NULL
)
return
NULL
;
result
=
Py_BuildValue
(
"(O(OOOO))"
,
self
->
base
.
ob_type
,
value
,
self
->
domain
?
self
->
domain
:
Py_None
,
self
->
default_
?
self
->
default_
:
Py_None
,
self
->
mapping
?
self
->
mapping
:
Py_None
);
Py_DECREF
(
value
);
return
result
;
}
static
PyMethodDef
Message_methods
[]
=
{
{
"__reduce__"
,
(
PyCFunction
)
Message_reduce
,
METH_NOARGS
,
"Reduce messages to a serializable form."
},
{
NULL
}
/* Sentinel */
};
static
char
MessageType__doc__
[]
=
"Message
\n
"
"
\n
"
"This is a string used as a message. It has a domain attribute that is
\n
"
"its source domain, and a default attribute that is its default text to
\n
"
"display when there is no translation. domain may be None meaning there is
\n
"
"no translation domain. default may also be None, in which case the
\n
"
"message id itself implicitly serves as the default text.
\n
"
;
statichere
PyTypeObject
MessageType
=
{
PyObject_HEAD_INIT
(
NULL
)
/* ob_size */
0
,
/* tp_name */
"zope.i18nmessageid.message."
"Message"
,
/* tp_basicsize */
sizeof
(
Message
),
/* tp_itemsize */
0
,
/* tp_dealloc */
(
destructor
)
&
Message_dealloc
,
/* tp_print */
(
printfunc
)
0
,
/* tp_getattr */
(
getattrfunc
)
0
,
/* tp_setattr */
(
setattrfunc
)
0
,
/* tp_compare */
(
cmpfunc
)
0
,
/* tp_repr */
(
reprfunc
)
0
,
/* tp_as_number */
0
,
/* tp_as_sequence */
0
,
/* tp_as_mapping */
0
,
/* tp_hash */
(
hashfunc
)
0
,
/* tp_call */
(
ternaryfunc
)
0
,
/* tp_str */
(
reprfunc
)
0
,
/* tp_getattro */
(
getattrofunc
)
0
,
/* tp_setattro */
(
setattrofunc
)
0
,
/* tp_as_buffer */
0
,
/* tp_flags */
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_BASETYPE
|
Py_TPFLAGS_HAVE_GC
,
/* tp_doc */
MessageType__doc__
,
/* tp_traverse */
(
traverseproc
)
Message_traverse
,
/* tp_clear */
(
inquiry
)
Message_clear
,
/* tp_richcompare */
(
richcmpfunc
)
0
,
/* tp_weaklistoffset */
(
long
)
0
,
/* tp_iter */
(
getiterfunc
)
0
,
/* tp_iternext */
(
iternextfunc
)
0
,
/* tp_methods */
Message_methods
,
/* tp_members */
Message_members
,
/* tp_getset */
0
,
/* tp_base */
0
,
/* tp_dict */
0
,
/* internal use */
/* tp_descr_get */
(
descrgetfunc
)
0
,
/* tp_descr_set */
(
descrsetfunc
)
0
,
/* tp_dictoffset */
0
,
/* tp_init */
(
initproc
)
0
,
/* tp_alloc */
(
allocfunc
)
0
,
/* tp_new */
(
newfunc
)
Message_new
,
/* tp_free */
0
,
/* Low-level free-mem routine */
/* tp_is_gc */
(
inquiry
)
0
,
/* For PyObject_IS_GC */
};
/* End of code for Message objects */
/* -------------------------------------------------------- */
/* List of methods defined in the module */
static
struct
PyMethodDef
_zope_i18nmessageid_message_methods
[]
=
{
{
NULL
,
(
PyCFunction
)
NULL
,
0
,
NULL
}
/* sentinel */
};
static
char
_zope_i18nmessageid_message_module_documentation
[]
=
"I18n Messages"
;
#ifndef PyMODINIT_FUNC
/* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
init_zope_i18nmessageid_message
(
void
)
{
PyObject
*
m
;
/* Initialize types: */
MessageType
.
tp_base
=
&
PyUnicode_Type
;
if
(
PyType_Ready
(
&
MessageType
)
<
0
)
return
;
/* Create the module and add the functions */
m
=
Py_InitModule3
(
"_zope_i18nmessageid_message"
,
_zope_i18nmessageid_message_methods
,
_zope_i18nmessageid_message_module_documentation
);
if
(
m
==
NULL
)
return
;
/* Add types: */
if
(
PyModule_AddObject
(
m
,
"Message"
,
(
PyObject
*
)
&
MessageType
)
<
0
)
return
;
}
src/zope/i18nmessageid/message.py
deleted
100644 → 0
View file @
10c59e84
##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""I18n Messages
$Id$
"""
__docformat__
=
"reStructuredText"
class
Message
(
unicode
):
"""Message (Python implementation)
This is a string used as a message. It has a domain attribute that is
its source domain, and a default attribute that is its default text to
display when there is no translation. domain may be None meaning there is
no translation domain. default may also be None, in which case the
message id itself implicitly serves as the default text.
These are the doc tests from message.txt. Note that we have to create the
message manually since MessageFactory would return the C implementation.
>>> from zope.i18nmessageid.message import pyMessage as Message
>>> robot = Message(u"robot-message", 'futurama', u"${name} is a robot.")
>>> robot
u'robot-message'
>>> isinstance(robot, unicode)
True
>>> robot.default
u'${name} is a robot.'
>>> robot.mapping
Only the python implementation has a _readonly attribute
>>> robot._readonly
True
>>> robot.domain = "planetexpress"
Traceback (most recent call last):
...
TypeError: readonly attribute
>>> robot.default = u"${name} is not a robot."
Traceback (most recent call last):
...
TypeError: readonly attribute
>>> robot.mapping = {u'name': u'Bender'}
Traceback (most recent call last):
...
TypeError: readonly attribute
>>> new_robot = Message(robot, mapping={u'name': u'Bender'})
>>> new_robot
u'robot-message'
>>> new_robot.domain
'futurama'
>>> new_robot.default
u'${name} is a robot.'
>>> new_robot.mapping
{u'name': u'Bender'}
>>> callable, args = new_robot.__reduce__()
>>> callable is Message
True
>>> args
(u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'})
>>> fembot = Message(u'fembot')
>>> callable, args = fembot.__reduce__()
>>> callable is Message
True
>>> args
(u'fembot', None, None, None)
Change classes for pickle tests
>>> import zope.i18nmessageid.message
>>> oldMessage = zope.i18nmessageid.message.Message
>>> zope.i18nmessageid.message.Message = Message
At first check if pickling and unpicklung from pyMessage to pyMessage works
>>> from pickle import dumps, loads
>>> pystate = dumps(new_robot)
>>> pickle_bot = loads(pystate)
>>> pickle_bot, pickle_bot.domain, pickle_bot.default, pickle_bot.mapping
(u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'})
>>> pickle_bot._readonly
True
>>> from zope.i18nmessageid.message import pyMessage
>>> pickle_bot.__reduce__()[0] is pyMessage
True
>>> del pickle_bot
At second check if cMessage is able to load the state of a pyMessage
>>> from _zope_i18nmessageid_message import Message
>>> zope.i18nmessageid.message.Message = Message
>>> c_bot = loads(pystate)
>>> c_bot, c_bot.domain, c_bot.default, c_bot.mapping
(u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'})
>>> c_bot._readonly
Traceback (most recent call last):
AttributeError: 'zope.i18nmessageid.message.Message' object has no attribute '_readonly'
>>> from _zope_i18nmessageid_message import Message as cMessage
>>> c_bot.__reduce__()[0] is cMessage
True
At last check if pyMessage can load a state of cMessage
>>> cstate = dumps(c_bot)
>>> del c_bot
>>> from zope.i18nmessageid.message import pyMessage as Message
>>> zope.i18nmessageid.message.Message = Message
>>> py_bot = loads(cstate)
>>> py_bot, py_bot.domain, py_bot.default, py_bot.mapping
(u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'})
>>> py_bot._readonly
True
>>> py_bot.__reduce__()[0] is pyMessage
True
Both pickle states should be equal
>>> pystate == cstate
True
Finally restore classes for other unit tests
>>> zope.i18nmessageid.message.Message = oldMessage
"""
__slots__
=
(
'domain'
,
'default'
,
'mapping'
,
'_readonly'
)
def
__new__
(
cls
,
ustr
,
domain
=
None
,
default
=
None
,
mapping
=
None
):
self
=
unicode
.
__new__
(
cls
,
ustr
)
if
isinstance
(
ustr
,
self
.
__class__
):
domain
=
ustr
.
domain
and
ustr
.
domain
[:]
or
domain
default
=
ustr
.
default
and
ustr
.
default
[:]
or
default
mapping
=
ustr
.
mapping
and
ustr
.
mapping
.
copy
()
or
mapping
ustr
=
unicode
(
ustr
)
self
.
domain
=
domain
if
default
is
None
:
# MessageID does: self.default = ustr
self
.
default
=
default
else
:
self
.
default
=
unicode
(
default
)
self
.
mapping
=
mapping
self
.
_readonly
=
True
return
self
def
__setattr__
(
self
,
key
,
value
):
"""Message is immutable
It cannot be changed once the message id is created.
"""
if
getattr
(
self
,
'_readonly'
,
False
):
raise
TypeError
(
'readonly attribute'
)
else
:
return
unicode
.
__setattr__
(
self
,
key
,
value
)
def
__reduce__
(
self
):
return
self
.
__class__
,
self
.
__getstate__
()
def
__getstate__
(
self
):
return
unicode
(
self
),
self
.
domain
,
self
.
default
,
self
.
mapping
# save a copy for the unit tests
pyMessage
=
Message
try
:
from
_zope_i18nmessageid_message
import
Message
except
ImportError
:
pass
class
MessageFactory
(
object
):
"""Factory for creating i18n messages."""
def
__init__
(
self
,
domain
):
self
.
_domain
=
domain
def
__call__
(
self
,
ustr
,
default
=
None
,
mapping
=
None
):
return
Message
(
ustr
,
self
.
_domain
,
default
,
mapping
)
src/zope/i18nmessageid/messageid.py
deleted
100644 → 0
View file @
10c59e84
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Message IDs.
$Id$
"""
import
zope.deprecation
zope
.
deprecation
.
deprecated
(
'MessageID'
,
'Mutable i18n messages ("message ids") have been '
'deprecated in favour of immutable ones and will '
'be removed in Zope 3.3. Please use '
'zope.i18nmessageid.Message instead.'
)
zope
.
deprecation
.
deprecated
(
'MessageIDFactory'
,
'Mutable i18n messages ("message ids") have been '
'deprecated in favour of immutable ones and will '
'be removed in Zope 3.3. Please use '
'use zope.i18nmessageid.MessageFactory instead.'
)
class
MessageID
(
unicode
):
"""Message ID.
This is a string used as a message ID. It has a domain attribute that is
its source domain, and a default attribute that is its default text to
display when there is no translation. domain may be None meaning there is
no translation domain. default may also be None, in which case the
message id itself implicitly serves as the default text.
MessageID objects also have a mapping attribute which must be set after
construction of the object. This is used when translating and
substituting variables.
To instanciate MessageIDs, it is recommended to use MessageIDFactory:
>>> fact = MessageIDFactory('test')
Now we can use the factory to make MessageIDs. Note that MessageID
is a subclass of unicode:
>>> id = fact(u'this is a test')
>>> isinstance(id, MessageID)
True
>>> isinstance(id, unicode)
True
Additional parameters, such as the i18n domain and the default
text are available through attributes:
>>> id.domain
'test'
>>> id.default
u'this is a test'
You can also reset the default text:
>>> id.default = u'blah'
>>> id.default
u'blah'
It is quite common to pass an abstract identifier as message id
and then a default text:
>>> id = fact(u'test-id', 'default test')
>>> id
u'test-id'
>>> id.default
u'default test'
>>> id.domain
'test'
"""
__slots__
=
(
'domain'
,
'default'
,
'mapping'
)
def
__new__
(
cls
,
ustr
,
domain
=
None
,
default
=
None
):
self
=
unicode
.
__new__
(
cls
,
ustr
)
self
.
domain
=
domain
if
default
is
None
:
self
.
default
=
ustr
else
:
self
.
default
=
unicode
(
default
)
self
.
mapping
=
{}
return
self
def
__getstate__
(
self
):
return
unicode
(
self
),
self
.
domain
,
self
.
default
,
self
.
mapping
def
__setstate__
(
self
,
(
ustr
,
domain
,
default
,
mapping
)):
super
(
MessageID
,
self
).
__init__
(
ustr
)
self
.
domain
=
domain
if
default
is
None
:
self
.
default
=
ustr
else
:
self
.
default
=
default
self
.
mapping
=
mapping
class
MessageIDFactory
(
object
):
"""Factory for creating MessageIDs."""
def
__init__
(
self
,
domain
):
self
.
_domain
=
domain
def
__call__
(
self
,
ustr
,
default
=
None
):
return
MessageID
(
ustr
,
self
.
_domain
,
default
)
src/zope/i18nmessageid/messages.txt
deleted
100644 → 0
View file @
10c59e84
=============
I18n Messages
=============
Rationale
---------
To translate any text, we must be able to discover the source domain
of the text. A source domain is an identifier that identifies a
project that produces program source strings. Source strings occur as
literals in python programs, text in templates, and some text in XML
data. The project implies a source language and an application
context.
We can think of a source domain as a collection of messages and
associated translation strings.
We often need to create unicode strings that will be displayed by
separate views. The view cannot translate the string without knowing
its source domain. A string or unicode literal carries no domain
information, therefore we use messages. Messages are unicode strings
which carry a translation source domain and possibly a default
translation. They are created by a message factory. The message
factory is created by calling ``MessageFactory`` with the source
domain.
Example
-------
In this example, we create a message factory and assign it to _. By
convention, we use _ as the name of our factory to be compatible with
translatable string extraction tools such as xgettext. We then call _
with a string that needs to be translatable:
>>> from zope.i18nmessageid import MessageFactory, Message
>>> _ = MessageFactory("futurama")
>>> robot = _(u"robot-message", u"${name} is a robot.")
Messages at first seem like they are unicode strings:
>>> robot
u'robot-message'
>>> isinstance(robot, unicode)
True
The additional domain, default and mapping information is available
through attributes:
>>> robot.default
u'${name} is a robot.'
>>> robot.mapping
>>> robot.domain
'futurama'
The message's attributes are considered part of the immutable message
object. They cannot be changed once the message id is created:
>>> robot.domain = "planetexpress"
Traceback (most recent call last):
...
TypeError: readonly attribute
>>> robot.default = u"${name} is not a robot."
Traceback (most recent call last):
...
TypeError: readonly attribute
>>> robot.mapping = {u'name': u'Bender'}
Traceback (most recent call last):
...
TypeError: readonly attribute
If you need to change their information, you'll have to make a new
message id object:
>>> new_robot = Message(robot, mapping={u'name': u'Bender'})
>>> new_robot
u'robot-message'
>>> new_robot.domain
'futurama'
>>> new_robot.default
u'${name} is a robot.'
>>> new_robot.mapping
{u'name': u'Bender'}
Last but not least, messages are reduceable for pickling:
>>> callable, args = new_robot.__reduce__()
>>> callable is Message
True
>>> args
(u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'})
>>> fembot = Message(u'fembot')
>>> callable, args = fembot.__reduce__()
>>> callable is Message
True
>>> args
(u'fembot', None, None, None)
Message IDs and backward compatability
--------------------------------------
The change to immutability is not a simple refactoring that can be
coped with backward compatible APIs--it is a change in semantics.
Because immutability is one of those "you either have it or you don't"
things (like pregnancy or death), we will not be able to support both
in one implementation.
The proposed solution for backward compatability is to support both
implementations in parallel, deprecating the mutable one. A separate
factory, ``MessageFactory``, instantiates immutable messages, while
the deprecated old one continues to work like before.
The roadmap to immutable-only message ids is proposed as follows:
Zope 3.1: Immutable message ids are introduced. Security
declarations for mutable message ids are provided to make the
stripping of security proxies unnecessary.
Zope 3.2: Mutable message ids are deprecated.
Zope 3.3: Mutable message ids are removed.
src/zope/i18nmessageid/tests.py
deleted
100644 → 0
View file @
10c59e84
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Message ID tests.
$Id$
"""
import
unittest
from
zope.testing.doctestunit
import
DocTestSuite
,
DocFileSuite
def
test_suite
():
return
unittest
.
TestSuite
((
DocTestSuite
(
'zope.i18nmessageid.messageid'
),
DocTestSuite
(
'zope.i18nmessageid.message'
),
DocFileSuite
(
'messages.txt'
,
package
=
'zope.i18nmessageid'
),
))
if
__name__
==
'__main__'
:
unittest
.
main
(
defaultTest
=
"test_suite"
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment