123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- # Copyright 2016 MongoDB, Inc.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- """Tools for working with `collations`_.
- .. _collations: http://userguide.icu-project.org/collation/concepts
- """
- from pymongo import common
- class CollationStrength(object):
- """
- An enum that defines values for `strength` on a
- :class:`~pymongo.collation.Collation`.
- """
- PRIMARY = 1
- """Differentiate base (unadorned) characters."""
- SECONDARY = 2
- """Differentiate character accents."""
- TERTIARY = 3
- """Differentiate character case."""
- QUATERNARY = 4
- """Differentiate words with and without punctuation."""
- IDENTICAL = 5
- """Differentiate unicode code point (characters are exactly identical)."""
- class CollationAlternate(object):
- """
- An enum that defines values for `alternate` on a
- :class:`~pymongo.collation.Collation`.
- """
- NON_IGNORABLE = 'non-ignorable'
- """Spaces and punctuation are treated as base characters."""
- SHIFTED = 'shifted'
- """Spaces and punctuation are *not* considered base characters.
- Spaces and punctuation are distinguished regardless when the
- :class:`~pymongo.collation.Collation` strength is at least
- :data:`~pymongo.collation.CollationStrength.QUATERNARY`.
- """
- class CollationMaxVariable(object):
- """
- An enum that defines values for `max_variable` on a
- :class:`~pymongo.collation.Collation`.
- """
- PUNCT = 'punct'
- """Both punctuation and spaces are ignored."""
- SPACE = 'space'
- """Spaces alone are ignored."""
- class CollationCaseFirst(object):
- """
- An enum that defines values for `case_first` on a
- :class:`~pymongo.collation.Collation`.
- """
- UPPER = 'upper'
- """Sort uppercase characters first."""
- LOWER = 'lower'
- """Sort lowercase characters first."""
- OFF = 'off'
- """Default for locale or collation strength."""
- class Collation(object):
- """Collation
- :Parameters:
- - `locale`: (string) The locale of the collation. This should be a string
- that identifies an `ICU locale ID` exactly. For example, ``en_US`` is
- valid, but ``en_us`` and ``en-US`` are not. Consult the MongoDB
- documentation for a list of supported locales.
- - `caseLevel`: (optional) If ``True``, turn on case sensitivity if
- `strength` is 1 or 2 (case sensitivity is implied if `strength` is
- greater than 2). Defaults to ``False``.
- - `caseFirst`: (optional) Specify that either uppercase or lowercase
- characters take precedence. Must be one of the following values:
- * :data:`~CollationCaseFirst.UPPER`
- * :data:`~CollationCaseFirst.LOWER`
- * :data:`~CollationCaseFirst.OFF` (the default)
- - `strength`: (optional) Specify the comparison strength. This is also
- known as the ICU comparison level. This must be one of the following
- values:
- * :data:`~CollationStrength.PRIMARY`
- * :data:`~CollationStrength.SECONDARY`
- * :data:`~CollationStrength.TERTIARY` (the default)
- * :data:`~CollationStrength.QUATERNARY`
- * :data:`~CollationStrength.IDENTICAL`
- Each successive level builds upon the previous. For example, a
- `strength` of :data:`~CollationStrength.SECONDARY` differentiates
- characters based both on the unadorned base character and its accents.
- - `numericOrdering`: (optional) If ``True``, order numbers numerically
- instead of in collation order (defaults to ``False``).
- - `alternate`: (optional) Specify whether spaces and punctuation are
- considered base characters. This must be one of the following values:
- * :data:`~CollationAlternate.NON_IGNORABLE` (the default)
- * :data:`~CollationAlternate.SHIFTED`
- - `maxVariable`: (optional) When `alternate` is
- :data:`~CollationAlternate.SHIFTED`, this option specifies what
- characters may be ignored. This must be one of the following values:
- * :data:`~CollationMaxVariable.PUNCT` (the default)
- * :data:`~CollationMaxVariable.SPACE`
- - `normalization`: (optional) If ``True``, normalizes text into Unicode
- NFD. Defaults to ``False``.
- - `backwards`: (optional) If ``True``, accents on characters are
- considered from the back of the word to the front, as it is done in some
- French dictionary ordering traditions. Defaults to ``False``.
- - `kwargs`: (optional) Keyword arguments supplying any additional options
- to be sent with this Collation object.
- .. versionadded: 3.4
- """
- __slots__ = ("__document",)
- def __init__(self, locale,
- caseLevel=None,
- caseFirst=None,
- strength=None,
- numericOrdering=None,
- alternate=None,
- maxVariable=None,
- normalization=None,
- backwards=None,
- **kwargs):
- locale = common.validate_string('locale', locale)
- self.__document = {'locale': locale}
- if caseLevel is not None:
- self.__document['caseLevel'] = common.validate_boolean(
- 'caseLevel', caseLevel)
- if caseFirst is not None:
- self.__document['caseFirst'] = common.validate_string(
- 'caseFirst', caseFirst)
- if strength is not None:
- self.__document['strength'] = common.validate_integer(
- 'strength', strength)
- if numericOrdering is not None:
- self.__document['numericOrdering'] = common.validate_boolean(
- 'numericOrdering', numericOrdering)
- if alternate is not None:
- self.__document['alternate'] = common.validate_string(
- 'alternate', alternate)
- if maxVariable is not None:
- self.__document['maxVariable'] = common.validate_string(
- 'maxVariable', maxVariable)
- if normalization is not None:
- self.__document['normalization'] = common.validate_boolean(
- 'normalization', normalization)
- if backwards is not None:
- self.__document['backwards'] = common.validate_boolean(
- 'backwards', backwards)
- self.__document.update(kwargs)
- @property
- def document(self):
- """The document representation of this collation.
- .. note::
- :class:`Collation` is immutable. Mutating the value of
- :attr:`document` does not mutate this :class:`Collation`.
- """
- return self.__document.copy()
- def __repr__(self):
- document = self.document
- return 'Collation(%s)' % (
- ', '.join('%s=%r' % (key, document[key]) for key in document),)
- def __eq__(self, other):
- if isinstance(other, Collation):
- return self.document == other.document
- return NotImplemented
- def __ne__(self, other):
- return not self == other
- def validate_collation_or_none(value):
- if value is None:
- return None
- if isinstance(value, Collation):
- return value.document
- if isinstance(value, dict):
- return value
- raise TypeError(
- 'collation must be a dict, an instance of collation.Collation, '
- 'or None.')
|