[Python-modules-commits] [twistar] 02/07: Import twistar_1.3.orig.tar.gz

Jan-Pascal van Best janpascal-guest at moszumanska.debian.org
Mon Oct 12 21:32:26 UTC 2015


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

janpascal-guest pushed a commit to branch master
in repository twistar.

commit d6c8cb13a3374c74749cecf7f32dd57e55cbb7aa
Author: Jan-Pascal van Best <janpascal at vanbest.org>
Date:   Wed Oct 7 16:29:55 2015 +0200

    Import twistar_1.3.orig.tar.gz
---
 .gitignore                          |   7 +
 .travis.yml                         |   6 +
 BermiInflector/BSD-LICENSE          |  15 +
 BermiInflector/Inflector.py         | 130 +++++++++
 BermiInflector/README.markdown      |  90 ++++++
 BermiInflector/Rules/Base.py        | 156 ++++++++++
 BermiInflector/Rules/English.py     | 156 ++++++++++
 BermiInflector/Rules/Spanish.py     | 167 +++++++++++
 BermiInflector/Rules/__init__.py    |   0
 BermiInflector/__init__.py          |   0
 BermiInflector/tests.py             | 129 +++++++++
 LICENSE                             |  25 ++
 Makefile                            |  11 +
 README.markdown                     |  80 ++++++
 doc/examples.xhtml                  | 226 +++++++++++++++
 doc/index.xhtml                     |  30 ++
 doc/lowlevel.xhtml                  |  57 ++++
 doc/relationship_examples.xhtml     | 239 ++++++++++++++++
 doc/stylesheet.css                  | 190 ++++++++++++
 doc/template.tpl                    |  31 ++
 setup.py                            |  17 ++
 twistar/__init__.py                 |  10 +
 twistar/dbconfig/__init__.py        |   4 +
 twistar/dbconfig/base.py            | 420 +++++++++++++++++++++++++++
 twistar/dbconfig/mysql.py           |  32 +++
 twistar/dbconfig/postgres.py        |  27 ++
 twistar/dbconfig/pyodbc.py          |  20 ++
 twistar/dbconfig/sqlite.py          |  40 +++
 twistar/dbobject.py                 | 557 ++++++++++++++++++++++++++++++++++++
 twistar/exceptions.py               |  48 ++++
 twistar/registry.py                 |  89 ++++++
 twistar/relationships.py            | 338 ++++++++++++++++++++++
 twistar/tests/README                |   7 +
 twistar/tests/__init__.py           |   0
 twistar/tests/mysql_config.py       |  53 ++++
 twistar/tests/postgres_config.py    |  79 +++++
 twistar/tests/sqlite_config.py      |  36 +++
 twistar/tests/test_dbconfig.py      | 155 ++++++++++
 twistar/tests/test_dbobject.py      | 257 +++++++++++++++++
 twistar/tests/test_relationships.py | 359 +++++++++++++++++++++++
 twistar/tests/test_transactions.py  |  68 +++++
 twistar/tests/test_utils.py         |  61 ++++
 twistar/tests/utils.py              |  55 ++++
 twistar/utils.py                    | 131 +++++++++
 twistar/validation.py               | 259 +++++++++++++++++
 45 files changed, 4867 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ba31055
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+apidoc/*
+doc/*.html
+*.pyc
+_trial_temp
+build
+dist
+twistar.egg-info
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..efeeb7c
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,6 @@
+language: python
+python:
+  - "2.7"
+  - "pypy"
+install: pip install . --use-mirrors
+script: trial twistar
diff --git a/BermiInflector/BSD-LICENSE b/BermiInflector/BSD-LICENSE
new file mode 100644
index 0000000..e43e42d
--- /dev/null
+++ b/BermiInflector/BSD-LICENSE
@@ -0,0 +1,15 @@
+Copyright (c) 2006 Bermi Ferrer Martinez
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software to deal in this software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of this software, and to permit
+persons to whom this software is furnished to do so, subject to the following
+condition:
+
+THIS 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 THIS SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THIS SOFTWARE.
\ No newline at end of file
diff --git a/BermiInflector/Inflector.py b/BermiInflector/Inflector.py
new file mode 100644
index 0000000..018ad47
--- /dev/null
+++ b/BermiInflector/Inflector.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2006 Bermi Ferrer Martinez
+#
+# bermi a-t bermilabs - com
+# See the end of this file for the free software, open source license (BSD-style).
+
+import re
+from Rules.English import English
+from Rules.Spanish import Spanish
+
+class Inflector :
+    """
+    Inflector for pluralizing and singularizing nouns.
+    
+    It provides methods for helping on creating programs
+    based on naming conventions like on Ruby on Rails.
+    """
+    
+    def __init__( self, Inflector = English ) :
+        assert callable(Inflector), "Inflector should be a callable obj"
+        self.Inflector = apply(Inflector);
+        
+    def pluralize(self, word) :
+        '''Pluralizes nouns.'''
+        return self.Inflector.pluralize(word)
+    
+    def singularize(self, word) :
+        '''Singularizes nouns.'''
+        return self.Inflector.singularize(word)
+    
+    def conditionalPlural(self, numer_of_records, word) :
+        '''Returns the plural form of a word if first parameter is greater than 1'''
+        return self.Inflector.conditionalPlural(numer_of_records, word)
+
+    def titleize(self, word, uppercase = '') :
+        '''Converts an underscored or CamelCase word into a sentence.
+            The titleize function converts text like "WelcomePage",
+            "welcome_page" or  "welcome page" to this "Welcome Page".
+            If the "uppercase" parameter is set to 'first' it will only
+            capitalize the first character of the title.'''
+        return self.Inflector.titleize(word, uppercase)
+
+    def camelize(self, word):
+        ''' Returns given word as CamelCased
+        Converts a word like "send_email" to "SendEmail". It
+        will remove non alphanumeric character from the word, so
+        "who's online" will be converted to "WhoSOnline"'''
+        return self.Inflector.camelize(word)
+    
+    def underscore(self, word) :
+        ''' Converts a word "into_it_s_underscored_version"
+        Convert any "CamelCased" or "ordinary Word" into an
+        "underscored_word".
+        This can be really useful for creating friendly URLs.'''
+        return self.Inflector.underscore(word)
+    
+    def humanize(self, word, uppercase = '') :
+        '''Returns a human-readable string from word
+        Returns a human-readable string from word, by replacing
+        underscores with a space, and by upper-casing the initial
+        character by default.
+        If you need to uppercase all the words you just have to
+        pass 'all' as a second parameter.'''
+        return self.Inflector.humanize(word, uppercase)
+    
+    
+    def variablize(self, word) :
+        '''Same as camelize but first char is lowercased
+        Converts a word like "send_email" to "sendEmail". It
+        will remove non alphanumeric character from the word, so
+        "who's online" will be converted to "whoSOnline"'''
+        return self.Inflector.variablize(word)
+    
+    def tableize(self, class_name) :
+        ''' Converts a class name to its table name according to rails
+        naming conventions. Example. Converts "Person" to "people" '''
+        return self.Inflector.tableize(class_name)
+    
+    def classify(self, table_name) :
+        '''Converts a table name to its class name according to rails
+        naming conventions. Example: Converts "people" to "Person" '''
+        return self.Inflector.classify(table_name)
+    
+    def ordinalize(self, number) :
+        '''Converts number to its ordinal form.
+        This method converts 13 to 13th, 2 to 2nd ...'''
+        return self.Inflector.ordinalize(number)
+    
+    
+    def unaccent(self, text) :
+        '''Transforms a string to its unaccented version. 
+        This might be useful for generating "friendly" URLs'''
+        return self.Inflector.unaccent(text)
+    
+    def urlize(self, text) :
+        '''Transform a string its unaccented and underscored
+        version ready to be inserted in friendly URLs'''
+        return self.Inflector.urlize(text)
+    
+    
+    def demodulize(self, module_name) :
+        return self.Inflector.demodulize(module_name)
+    
+    def modulize(self, module_description) :
+        return self.Inflector.modulize(module_description)
+    
+    def foreignKey(self, class_name, separate_class_name_and_id_with_underscore = 1) :
+        ''' Returns class_name in underscored form, with "_id" tacked on at the end. 
+        This is for use in dealing with the database.'''
+        return self.Inflector.foreignKey(class_name, separate_class_name_and_id_with_underscore)
+    
+
+
+
+# Copyright (c) 2006 Bermi Ferrer Martinez
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software to deal in this software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of this software, and to permit
+# persons to whom this software is furnished to do so, subject to the following
+# condition:
+#
+# THIS 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 THIS SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THIS SOFTWARE.
\ No newline at end of file
diff --git a/BermiInflector/README.markdown b/BermiInflector/README.markdown
new file mode 100644
index 0000000..580285f
--- /dev/null
+++ b/BermiInflector/README.markdown
@@ -0,0 +1,90 @@
+# Inflector for Python
+
+The Inflector is used for getting the plural and singular form of nouns. This piece of code helps on creating code that favors convention over configuration.
+
+Only English and Spanish nouns are supported. The English version is a port of Ruby on Rails Inflector, while the Spanish Version has been developed from scratch with the help of Carles Sadurní.
+
+Apart from converting singulars and plurals, this module also handles necessary string conversion for convention based applications like:
+
+Available methods are:
+
+## pluralize(word)
+
+Pluralizes nouns.
+
+## singularize(word)
+
+Singularizes nouns.
+
+## conditionalPlural(numer_of_records, word)
+
+Returns the plural form of a word if first parameter is greater than 1
+
+## titleize(word, uppercase = '')
+
+Converts an underscored or CamelCase word into a sentence.
+The titleize function converts text like "WelcomePage",
+"welcome_page" or  "welcome page" to this "Welcome Page".
+If the "uppercase" parameter is set to 'first' it will only
+capitalize the first character of the title.
+
+## camelize(word):
+
+Returns given word as CamelCased
+Converts a word like "send_email" to "SendEmail". It
+will remove non alphanumeric character from the word, so
+"who's online" will be converted to "WhoSOnline"
+
+## underscore(word)
+
+Converts a word "into_it_s_underscored_version"
+Convert any "CamelCased" or "ordinary Word" into an
+"underscored_word".
+This can be really useful for creating friendly URLs.
+
+## humanize(word, uppercase = '')
+
+Returns a human-readable string from word
+Returns a human-readable string from word, by replacing
+underscores with a space, and by upper-casing the initial
+character by default.
+If you need to uppercase all the words you just have to
+pass 'all' as a second parameter.
+
+
+## variablize(word)
+
+Same as camelize but first char is lowercased
+Converts a word like "send_email" to "sendEmail". It
+will remove non alphanumeric character from the word, so
+"who's online" will be converted to "whoSOnline"
+return self.Inflector.variablize(word)
+
+## tableize(class_name)
+
+Converts a class name to its table name according to rails
+naming conventions. Example. Converts "Person" to "people" 
+
+## classify(table_name)
+
+Converts a table name to its class name according to rails
+naming conventions. Example: Converts "people" to "Person" 
+
+## ordinalize(number)
+Converts number to its ordinal form.
+This method converts 13 to 13th, 2 to 2nd ...
+
+## unaccent(text)
+
+Transforms a string to its unaccented version. 
+This might be useful for generating "friendly" URLs
+
+## urlize(text)
+
+Transform a string its unaccented and underscored
+version ready to be inserted in friendly URLs
+
+## foreignKey(class_name, separate_class_name_and_id_with_underscore = 1)
+
+Returns class_name in underscored form, with "_id" tacked on at the end. 
+This is for use in dealing with the database.
diff --git a/BermiInflector/Rules/Base.py b/BermiInflector/Rules/Base.py
new file mode 100644
index 0000000..99f3d3b
--- /dev/null
+++ b/BermiInflector/Rules/Base.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2006 Bermi Ferrer Martinez
+# bermi a-t bermilabs - com
+# See the end of this file for the free software, open source license (BSD-style).
+
+import re
+
+class Base:
+    '''Locale inflectors must inherit from this base class inorder to provide
+    the basic Inflector functionality'''
+    
+    def conditionalPlural(self, numer_of_records, word) :
+        '''Returns the plural form of a word if first parameter is greater than 1'''
+        
+        if numer_of_records > 1 :
+            return self.pluralize(word)
+        else :
+            return word
+
+
+    def titleize(self, word, uppercase = '') :
+        '''Converts an underscored or CamelCase word into a English sentence.
+            The titleize function converts text like "WelcomePage",
+            "welcome_page" or  "welcome page" to this "Welcome Page".
+            If second parameter is set to 'first' it will only
+            capitalize the first character of the title.'''
+    
+        if(uppercase == 'first'):
+            return self.humanize(self.underscore(word)).capitalize()
+        else :
+            return self.humanize(self.underscore(word)).title()
+
+
+    def camelize(self, word):
+        ''' Returns given word as CamelCased
+        Converts a word like "send_email" to "SendEmail". It
+        will remove non alphanumeric character from the word, so
+        "who's online" will be converted to "WhoSOnline"'''
+        return ''.join(w[0].upper() + w[1:] for w in re.sub('[^A-Z^a-z^0-9^:]+', ' ', word).split(' '))
+    
+    def underscore(self, word) :
+        ''' Converts a word "into_it_s_underscored_version"
+        Convert any "CamelCased" or "ordinary Word" into an
+        "underscored_word".
+        This can be really useful for creating friendly URLs.'''
+        
+        return  re.sub('[^A-Z^a-z^0-9^\/]+','_', \
+                re.sub('([a-z\d])([A-Z])','\\1_\\2', \
+                re.sub('([A-Z]+)([A-Z][a-z])','\\1_\\2', re.sub('::', '/',word)))).lower()
+    
+    
+    def humanize(self, word, uppercase = '') :
+        '''Returns a human-readable string from word
+        Returns a human-readable string from word, by replacing
+        underscores with a space, and by upper-casing the initial
+        character by default.
+        If you need to uppercase all the words you just have to
+        pass 'all' as a second parameter.'''
+        
+        if(uppercase == 'first'):
+            return re.sub('_id$', '', word).replace('_',' ').capitalize()
+        else :
+            return re.sub('_id$', '', word).replace('_',' ').title()
+    
+    
+    def variablize(self, word) :
+        '''Same as camelize but first char is lowercased
+        Converts a word like "send_email" to "sendEmail". It
+        will remove non alphanumeric character from the word, so
+        "who's online" will be converted to "whoSOnline"'''
+        word = self.camelize(word)
+        return word[0].lower()+word[1:]
+    
+    def tableize(self, class_name) :
+        ''' Converts a class name to its table name according to rails
+        naming conventions. Example. Converts "Person" to "people" '''
+        return self.pluralize(self.underscore(class_name))
+    
+    
+    def classify(self, table_name) :
+        '''Converts a table name to its class name according to rails
+        naming conventions. Example: Converts "people" to "Person" '''
+        return self.camelize(self.singularize(table_name))
+    
+    
+    def ordinalize(self, number) :
+        '''Converts number to its ordinal English form.
+        This method converts 13 to 13th, 2 to 2nd ...'''
+        tail = 'th'
+        if number % 100 == 11 or number % 100 == 12 or number % 100 == 13:
+            tail = 'th'
+        elif number % 10 == 1 :
+            tail = 'st'
+        elif number % 10 == 2 :
+            tail = 'nd'
+        elif number % 10 == 3 :
+            tail = 'rd'
+        
+        return str(number)+tail
+    
+    
+    def unaccent(self, text) :
+        '''Transforms a string to its unaccented version. 
+        This might be useful for generating "friendly" URLs'''
+        find = u'\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F8\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF'
+        replace = u'AAAAAAACEEEEIIIIDNOOOOOOUUUUYTsaaaaaaaceeeeiiiienoooooouuuuyty'
+        return self.string_replace(text, find, replace)
+    
+    def string_replace (self, word, find, replace) :
+        '''This function returns a copy of word, translating
+        all occurrences of each character in find to the
+        corresponding character in replace'''
+        for k in range(0,len(find)) :
+            word = re.sub(find[k], replace[k], word)
+            
+        return word
+    
+    def urlize(self, text) :
+        '''Transform a string its unaccented and underscored
+        version ready to be inserted in friendly URLs'''
+        return re.sub('^_|_$','',self.underscore(self.unaccent(text)))
+    
+    
+    def demodulize(self, module_name) :
+        return self.humanize(self.underscore(re.sub('^.*::','',module_name)))
+    
+    def modulize(self, module_description) :
+        return self.camelize(self.singularize(module_description))
+    
+    def foreignKey(self, class_name, separate_class_name_and_id_with_underscore = 1) :
+        ''' Returns class_name in underscored form, with "_id" tacked on at the end. 
+        This is for use in dealing with the database.'''
+        if separate_class_name_and_id_with_underscore :
+            tail = '_id'
+        else :
+            tail = 'id'
+        return self.underscore(self.demodulize(class_name))+tail;
+
+
+
+# Copyright (c) 2006 Bermi Ferrer Martinez
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software to deal in this software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of this software, and to permit
+# persons to whom this software is furnished to do so, subject to the following
+# condition:
+#
+# THIS 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 THIS SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THIS SOFTWARE.
\ No newline at end of file
diff --git a/BermiInflector/Rules/English.py b/BermiInflector/Rules/English.py
new file mode 100644
index 0000000..25d78ee
--- /dev/null
+++ b/BermiInflector/Rules/English.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2006 Bermi Ferrer Martinez
+# bermi a-t bermilabs - com
+#
+# See the end of this file for the free software, open source license (BSD-style).
+
+import re
+from Base import Base
+
+class English (Base):
+    """
+    Inflector for pluralize and singularize English nouns.
+    
+    This is the default Inflector for the Inflector obj
+    """
+    
+    def pluralize(self, word) :
+        '''Pluralizes English nouns.'''
+        
+        rules = [
+            ['(?i)(quiz)$' , '\\1zes'],
+            ['^(?i)(ox)$' , '\\1en'],
+            ['(?i)([m|l])ouse$' , '\\1ice'],
+            ['(?i)(matr|vert|ind)ix|ex$' , '\\1ices'],
+            ['(?i)(x|ch|ss|sh)$' , '\\1es'],
+            ['(?i)([^aeiouy]|qu)ies$' , '\\1y'],
+            ['(?i)([^aeiouy]|qu)y$' , '\\1ies'],
+            ['(?i)(hive)$' , '\\1s'],
+            ['(?i)(?:([^f])fe|([lr])f)$' , '\\1\\2ves'],
+            ['(?i)sis$' , 'ses'],
+            ['(?i)([ti])um$' , '\\1a'],
+            ['(?i)(buffal|tomat)o$' , '\\1oes'],
+            ['(?i)(bu)s$' , '\\1ses'],
+            ['(?i)(alias|status)' , '\\1es'],
+            ['(?i)(octop|vir)us$' , '\\1i'],
+            ['(?i)(ax|test)is$' , '\\1es'],
+            ['(?i)s$' , 's'],
+            ['(?i)$' , 's']
+        ]
+        
+        uncountable_words = ['equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep']
+        
+        irregular_words = {
+            'person' : 'people',
+            'man' : 'men',
+            'child' : 'children',
+            'sex' : 'sexes',
+            'move' : 'moves'
+        }
+        
+        lower_cased_word = word.lower();
+        
+        for uncountable_word in uncountable_words:
+            if lower_cased_word[-1*len(uncountable_word):] == uncountable_word :
+                return word
+        
+        for irregular in irregular_words.keys():
+            match = re.search('('+irregular+')$',word, re.IGNORECASE)
+            if match:
+                return re.sub('(?i)'+irregular+'$', match.expand('\\1')[0]+irregular_words[irregular][1:], word)
+        
+        for rule in range(len(rules)):
+            match = re.search(rules[rule][0], word, re.IGNORECASE)
+            if match :
+                groups = match.groups()
+                for k in range(0,len(groups)) :
+                    if groups[k] == None :
+                        rules[rule][1] = rules[rule][1].replace('\\'+str(k+1), '')
+                        
+                return re.sub(rules[rule][0], rules[rule][1], word)
+        
+        return word
+
+
+    def singularize (self, word) :
+        '''Singularizes English nouns.'''
+        
+        rules = [
+            ['(?i)(quiz)zes$' , '\\1'],
+            ['(?i)(matr)ices$' , '\\1ix'],
+            ['(?i)(vert|ind)ices$' , '\\1ex'],
+            ['(?i)^(ox)en' , '\\1'],
+            ['(?i)(alias|status)es$' , '\\1'],
+            ['(?i)([octop|vir])i$' , '\\1us'],
+            ['(?i)(cris|ax|test)es$' , '\\1is'],
+            ['(?i)(shoe)s$' , '\\1'],
+            ['(?i)(o)es$' , '\\1'],
+            ['(?i)(bus)es$' , '\\1'],
+            ['(?i)([m|l])ice$' , '\\1ouse'],
+            ['(?i)(x|ch|ss|sh)es$' , '\\1'],
+            ['(?i)(m)ovies$' , '\\1ovie'],
+            ['(?i)(s)eries$' , '\\1eries'],
+            ['(?i)([^aeiouy]|qu)ies$' , '\\1y'],
+            ['(?i)([lr])ves$' , '\\1f'],
+            ['(?i)(tive)s$' , '\\1'],
+            ['(?i)(hive)s$' , '\\1'],
+            ['(?i)([^f])ves$' , '\\1fe'],
+            ['(?i)(^analy)ses$' , '\\1sis'],
+            ['(?i)((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$' , '\\1\\2sis'],
+            ['(?i)([ti])a$' , '\\1um'],
+            ['(?i)(n)ews$' , '\\1ews'],
+            ['(?i)s$' , ''],
+        ];
+    
+        uncountable_words = ['equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep','sms'];
+    
+        irregular_words = {
+            'people' : 'person',
+            'men' : 'man',
+            'children' : 'child',
+            'sexes' : 'sex',
+            'moves' : 'move'
+        }
+    
+        lower_cased_word = word.lower();
+    
+        for uncountable_word in uncountable_words:
+            if lower_cased_word[-1*len(uncountable_word):] == uncountable_word :
+                return word
+            
+        for irregular in irregular_words.keys():
+            match = re.search('('+irregular+')$',word, re.IGNORECASE)
+            if match:
+                return re.sub('(?i)'+irregular+'$', match.expand('\\1')[0]+irregular_words[irregular][1:], word)
+            
+
+        for rule in range(len(rules)):
+            match = re.search(rules[rule][0], word, re.IGNORECASE)
+            if match :
+                groups = match.groups()
+                for k in range(0,len(groups)) :
+                    if groups[k] == None :
+                        rules[rule][1] = rules[rule][1].replace('\\'+str(k+1), '')
+                        
+                return re.sub(rules[rule][0], rules[rule][1], word)
+        
+        return word
+    
+
+
+# Copyright (c) 2006 Bermi Ferrer Martinez
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software to deal in this software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of this software, and to permit
+# persons to whom this software is furnished to do so, subject to the following
+# condition:
+#
+# THIS 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 THIS SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THIS SOFTWARE.
\ No newline at end of file
diff --git a/BermiInflector/Rules/Spanish.py b/BermiInflector/Rules/Spanish.py
new file mode 100644
index 0000000..7b0d3b3
--- /dev/null
+++ b/BermiInflector/Rules/Spanish.py
@@ -0,0 +1,167 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2006 Bermi Ferrer Martinez
+# Copyright (c) 2006 Carles Sadurn� Anguita
+#
+# bermi a-t bermilabs - com
+#
+# See the end of this file for the free software, open source license (BSD-style).
+
+import re
+from Base import Base
+
+class Spanish (Base):
+    '''
+    Inflector for pluralize and singularize Spanish nouns.
+    '''
+    
+    def pluralize(self, word) :
+        '''Pluralizes Spanish nouns.'''
+        rules = [
+            ['(?i)([aeiou])x$', '\\1x'], # This could fail if the word is oxytone.
+            ['(?i)([�����])([ns])$', '|1\\2es'],
+            ['(?i)(^[bcdfghjklmn�pqrstvwxyz]*)an$', '\\1anes'], # clan->clanes
+            ['(?i)([�����])s$', '|1ses'],
+            ['(?i)(^[bcdfghjklmn�pqrstvwxyz]*)([aeiou])([ns])$', '\\1\\2\\3es'], # tren->trenes
+            ['(?i)([aeiou���])$', '\\1s'], # casa->casas, padre->padres, pap�->pap�s
+            ['(?i)([aeiou])s$', '\\1s'], # atlas->atlas, virus->virus, etc.
+            ['(?i)([��])(s)$', '|1\\2es'], # ingl�s->ingleses
+            ['(?i)z$', 'ces'],  # luz->luces
+            ['(?i)([��])$', '\\1es'], # ceut�->ceut�es, tab�->tab�es
+            ['(?i)(ng|[wckgtp])$', '\\1s'], # Anglicismos como puenting, frac, crack, show (En que casos podr�a fallar esto?)
+            ['(?i)$', 'es']	# ELSE +es (v.g. �rbol->�rboles)
+        ]
+        
+        uncountable_words = ['tijeras','gafas', 'vacaciones','v�veres','d�ficit']
+        ''' In fact these words have no singular form: you cannot say neither
+        "una gafa" nor "un v�vere". So we should change the variable name to
+        onlyplural or something alike.'''
+        
+        irregular_words = {
+            'pa�s' : 'pa�ses',
+            'champ�' : 'champ�s',
+            'jersey' : 'jers�is',
+            'car�cter' : 'caracteres',
+            'esp�cimen' : 'espec�menes',
+            'men�' : 'men�s',
+            'r�gimen' : 'reg�menes',
+            'curriculum'  :  'curr�culos',
+            'ultim�tum'  :  'ultimatos',
+            'memor�ndum'  :  'memorandos',
+            'refer�ndum'  :  'referendos'
+        }
+        
+        lower_cased_word = word.lower();
+        
+        for uncountable_word in uncountable_words:
+            if lower_cased_word[-1*len(uncountable_word):] == uncountable_word :
+                return word
+        
+        for irregular in irregular_words.keys():
+            match = re.search('(?i)('+irregular+')$',word, re.IGNORECASE)
+            if match:
+                return re.sub('(?i)'+irregular+'$', match.expand('\\1')[0]+irregular_words[irregular][1:], word)
+        
+        
+        for rule in range(len(rules)):
+            match = re.search(rules[rule][0], word, re.IGNORECASE)
+            
+            if match :
+                groups = match.groups()
+                replacement = rules[rule][1]
+                if re.match('\|', replacement) :
+                    for k in range(1, len(groups)) :
+                        replacement = replacement.replace('|'+str(k), self.string_replace(groups[k-1], '����������', 'AEIOUaeiou'))
+                
+                result = re.sub(rules[rule][0], replacement, word)
+                # Esto acentua los sustantivos que al pluralizarse se convierten en esdr�julos como esm�quines, j�venes...
+                match = re.search('(?i)([aeiou]).{1,3}([aeiou])nes$',result)
+                
+                if match and len(match.groups()) > 1 and not re.search('(?i)[�����]', word) :
+                    result = result.replace(match.group(0), self.string_replace(match.group(1), 'AEIOUaeiou', '����������') + match.group(0)[1:])
+                    
+                return result
+        
+        return word
+
+
+    def singularize (self, word) :
+        '''Singularizes Spanish nouns.'''
+        
+        rules = [
+            ['(?i)^([bcdfghjklmn�pqrstvwxyz]*)([aeiou])([ns])es$', '\\1\\2\\3'],
+            ['(?i)([aeiou])([ns])es$',  '~1\\2'],
+            ['(?i)oides$',  'oide'], # androides->androide
+            ['(?i)(ces)$/i', 'z'],
+            ['(?i)(sis|tis|xis)+$',  '\\1'], # crisis, apendicitis, praxis
+            ['(?i)(�)s$',  '\\1'], # beb�s->beb�
+            ['(?i)([^e])s$',  '\\1'], # casas->casa
+            ['(?i)([bcdfghjklmn�prstvwxyz]{2,}e)s$', '\\1'], # cofres->cofre
+            ['(?i)([gh�pv]e)s$', '\\1'], # 24-01 llaves->llave
+            ['(?i)es$', ''] # ELSE remove _es_  monitores->monitor
+        ];
+    
+        uncountable_words = ['paraguas','tijeras', 'gafas', 'vacaciones', 'v�veres','lunes','martes','mi�rcoles','jueves','viernes','cumplea�os','virus','atlas','sms']
+        
+        irregular_words = {
+            'jersey':'jers�is',
+            'esp�cimen':'espec�menes',
+            'car�cter':'caracteres',
+            'r�gimen':'reg�menes',
+            'men�':'men�s',
+            'r�gimen':'reg�menes',
+            'curriculum' : 'curr�culos',
+            'ultim�tum' : 'ultimatos',
+            'memor�ndum' : 'memorandos',
+            'refer�ndum' : 'referendos',
+            's�ndwich' : 's�ndwiches'
+        }
+    
+        lower_cased_word = word.lower();
+    
+        for uncountable_word in uncountable_words:
+            if lower_cased_word[-1*len(uncountable_word):] == uncountable_word :
+                return word
+            
+        for irregular in irregular_words.keys():
+            match = re.search('('+irregular+')$',word, re.IGNORECASE)
+            if match:
+                return re.sub('(?i)'+irregular+'$', match.expand('\\1')[0]+irregular_words[irregular][1:], word)
+            
+        for rule in range(len(rules)):
+            match = re.search(rules[rule][0], word, re.IGNORECASE)
+            if match :
+                groups = match.groups()
+                replacement = rules[rule][1]
+                if re.match('~', replacement) :
+                    for k in range(1, len(groups)) :
+                        replacement = replacement.replace('~'+str(k), self.string_replace(groups[k-1], 'AEIOUaeiou', '����������'))
+                
+                result = re.sub(rules[rule][0], replacement, word)
+                # Esta es una posible soluci�n para el problema de dobles acentos. Un poco guarrillo pero funciona
+                match = re.search('(?i)([�����]).*([�����])',result)
+                
+                if match and len(match.groups()) > 1 and not re.search('(?i)[�����]', word) :
+                    result = self.string_replace(result, '����������', 'AEIOUaeiou')
+                
+                return result
+        
+        return word
+
+
+# Copyright (c) 2006 Bermi Ferrer Martinez
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software to deal in this software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of this software, and to permit
+# persons to whom this software is furnished to do so, subject to the following
+# condition:
+#
+# THIS 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 THIS SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THIS SOFTWARE.
\ No newline at end of file
diff --git a/BermiInflector/Rules/__init__.py b/BermiInflector/Rules/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/BermiInflector/__init__.py b/BermiInflector/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/BermiInflector/tests.py b/BermiInflector/tests.py
new file mode 100644
index 0000000..1525c50
--- /dev/null
+++ b/BermiInflector/tests.py
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2006 Bermi Ferrer Martinez
+#
+# bermi a-t bermilabs - com
+#
+import unittest
+from Inflector import Inflector, English, Spanish
+
+class EnglishInflectorTestCase(unittest.TestCase):
+    singular_to_plural = {
+        "search"      : "searches",
+        "switch"      : "switches",
+        "fix"         : "fixes",
+        "box"         : "boxes",
+        "process"     : "processes",
+        "address"     : "addresses",
+        "case"        : "cases",
+        "stack"       : "stacks",
+        "wish"        : "wishes",
+        "fish"        : "fish",
+    
+        "category"    : "categories",
+        "query"       : "queries",
+        "ability"     : "abilities",
+        "agency"      : "agencies",
+        "movie"       : "movies",
+    
+        "archive"     : "archives",
+    
+        "index"       : "indices",
+    
+        "wife"        : "wives",
+        "safe"        : "saves",
+        "half"        : "halves",
+    
+        "move"        : "moves",
+    
+        "salesperson" : "salespeople",
+        "person"      : "people",
+    
+        "spokesman"   : "spokesmen",
+        "man"         : "men",
+        "woman"       : "women",
+    
+        "basis"       : "bases",
+        "diagnosis"   : "diagnoses",
+    
+        "datum"       : "data",
+        "medium"      : "media",
+        "analysis"    : "analyses",
+    
+        "node_child"  : "node_children",
+        "child"       : "children",
+    
+        "experience"  : "experiences",
+        "day"         : "days",
+    
+        "comment"     : "comments",
+        "foobar"      : "foobars",
+        "newsletter"  : "newsletters",
+    
+        "old_news"    : "old_news",
+        "news"        : "news",
+    
+        "series"      : "series",
+        "species"     : "species",
+    
+        "quiz"        : "quizzes",
+    
+        "perspective" : "perspectives",
+    
+        "ox" : "oxen",
+        "photo" : "photos",
+        "buffalo" : "buffaloes",
+        "tomato" : "tomatoes",
+        "dwarf" : "dwarves",
+        "elf" : "elves",
+        "information" : "information",
+        "equipment" : "equipment",
+        "bus" : "buses",
+        "status" : "statuses",
+        "mouse" : "mice",
+    
+        "louse" : "lice",
+        "house" : "houses",
+        "octopus" : "octopi",
+        "virus" : "viri",
+        "alias" : "aliases",
+        "portfolio" : "portfolios",
+    
+        "vertex" : "vertices",
+        "matrix" : "matrices",
+    
+        "axis" : "axes",
+        "testis" : "testes",
+        "crisis" : "crises",
+    
+        "rice" : "rice",
+        "shoe" : "shoes",
+    
+        "horse" : "horses",
+        "prize" : "prizes",
+        "edge" : "edges"
+    }
+    def setUp(self):
+        self.inflector = Inflector(English)
+    
+    def tearDown(self):
+        self.inflector = None
+
+    def test_pluralize(self) :
+        for singular in self.singular_to_plural.keys() :
+            assert self.inflector.pluralize(singular) == self.singular_to_plural[singular], \
+            'English Inlector pluralize(%s) should produce "%s" and NOT "%s"' % (singular, self.singular_to_plural[singular], self.inflector.pluralize(singular))
+            
+    def test_singularize(self) :
+        for singular in self.singular_to_plural.keys() :
+            assert self.inflector.singularize(self.singular_to_plural[singular]) == singular, \
+            'English Inlector singularize(%s) should produce "%s" and NOT "%s"' % (self.singular_to_plural[singular], singular, self.inflector.singularize(self.singular_to_plural[singular]))
+
+
+
+InflectorTestSuite = unittest.TestSuite()
+InflectorTestSuite.addTest(EnglishInflectorTestCase("test_pluralize"))
+InflectorTestSuite.addTest(EnglishInflectorTestCase("test_singularize"))
+runner = unittest.TextTestRunner()
+runner.run(InflectorTestSuite)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..92ee54f
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,25 @@
+The files in the BermiInflector directory are released under the 
+license described in the file BSD-LICENSE found in that folder.
+All other code is released with the following copyright and under
+the following license:
+
+Copyright (c) 2010 Butterfat, LLC
+
+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 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,
... 4188 lines suppressed ...

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



More information about the Python-modules-commits mailing list