Skip to content

Commit 8fb87cd

Browse files
committed
Use the inflect library for better singularization of table names
1 parent 651a1be commit 8fb87cd

5 files changed

Lines changed: 20 additions & 23 deletions

File tree

CHANGES.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ Version history
44
1.1.0
55
-----
66

7-
* Revamped the API
8-
97
* Added automatic detection of joined-table inheritance
108

119
* Fixed missing class name prefix in primary/secondary joins in relationships
1210

1311
* Instead of wildcard imports, generate explicit imports dynamically (fixes #1)
1412

13+
* Use the inflect library to produce better guesses for table to class name conversion
14+
1515
* Automatically detect Boolean columns based on CheckConstraints
1616

1717
* Skip redundant CheckConstraints for Enum and Boolean columns

setup.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
from setuptools import setup, find_packages
55

66

7-
extra_requirements = ('argparse',) if sys.version_info < (2, 7) else ()
7+
extra_requirements = ()
8+
dependency_links = []
9+
if sys.version_info < (2, 7):
10+
extra_requirements = ('argparse',)
11+
elif sys.version_info > (3,):
12+
dependency_links = ['https://github.com/benthor/inflect.py/archive/master.zip#egg=inflect-0.2.3']
13+
814
here = os.path.dirname(__file__)
915
readme_path = os.path.join(here, 'README.rst')
1016
readme = open(readme_path).read()
@@ -13,7 +19,7 @@
1319
name='sqlacodegen',
1420
description='Automatic model code generator for SQLAlchemy',
1521
long_description=readme,
16-
version='1.1.0.pre2',
22+
version='1.1.0.pre3',
1723
author='Alex Gronholm',
1824
author_email='sqlacodegen@nextday.fi',
1925
url='http://pypi.python.org/pypi/sqlacodegen/',
@@ -34,7 +40,9 @@
3440
packages=find_packages(exclude=['tests']),
3541
install_requires=(
3642
'sqlalchemy >= 0.6.0',
43+
'inflect >= 0.2.0'
3744
) + extra_requirements,
45+
dependency_links=dependency_links,
3846
test_suite='nose.collector',
3947
tests_require=['nose'],
4048
zip_safe=False,

sqlacodegen/codegen.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from sqlalchemy.util import OrderedDict
1212
from sqlalchemy.types import Boolean, String
1313
import sqlalchemy
14+
import inflect
1415

1516
try:
1617
from sqlalchemy.sql.expression import TextClause
@@ -23,18 +24,11 @@
2324
_re_enum_check_constraint = re.compile(r"(?:(?:.*?)\.)?(.*?) IN \((.+)\)")
2425
_re_enum_item = re.compile(r"'(.*?)(?<!\\)'")
2526

26-
27-
def _singular(plural):
28-
"""A feeble attempt at converting plural English nouns into singular form."""
29-
if plural.endswith('ies'):
30-
return plural[:-3] + 'y'
31-
if plural.endswith('s') and not plural.endswith('ss'):
32-
return plural[:-1]
33-
return plural
27+
inflect_engine = inflect.engine()
3428

3529

3630
def _tablename_to_classname(tablename):
37-
return _singular(''.join(part.capitalize() for part in tablename.split('_')))
31+
return inflect_engine.singular_noun(''.join(part.capitalize() for part in tablename.split('_')))
3832

3933

4034
def _get_compiled_expression(statement):
@@ -358,7 +352,7 @@ def __init__(self, source_cls, target_cls, constraint):
358352

359353
colname = constraint.columns[0]
360354
tablename = constraint.elements[0].column.table.name
361-
self.preferred_name = _singular(tablename) if not colname.endswith('_id') else colname[:-3]
355+
self.preferred_name = inflect_engine.singular_noun(tablename) if not colname.endswith('_id') else colname[:-3]
362356

363357
# Add uselist=False to One-to-One relationships
364358
if any(isinstance(c, (PrimaryKeyConstraint, UniqueConstraint)) and

test/test_codegen.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from sqlalchemy.dialects.postgresql.base import BIGINT, DOUBLE_PRECISION, BOOLEAN, ENUM
1111
from sqlalchemy.dialects.mysql.base import TINYINT
1212

13-
from sqlacodegen.codegen import CodeGenerator, _singular
13+
from sqlacodegen.codegen import CodeGenerator
1414

1515

1616
if sys.version_info < (3,):
@@ -22,14 +22,6 @@ def remove_unicode_prefixes(text):
2222
remove_unicode_prefixes = lambda text: text
2323

2424

25-
def test_singular_ies():
26-
eq_(_singular('bunnies'), 'bunny')
27-
28-
29-
def test_singular_ss():
30-
eq_(_singular('address'), 'address')
31-
32-
3325
class TestCodeGenerator(object):
3426
def setup(self):
3527
self.metadata = MetaData(create_engine('sqlite:///'))

tox.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@ envlist = py26,py27,py32,py33,py26-sqla07,py26-sqla06
33

44
[testenv]
55
deps=nose
6+
https://github.com/benthor/inflect.py/archive/master.zip#egg=inflect-0.2.3
67
sqlalchemy<=0.8.99
78
commands=nosetests []
89

910
[testenv:py26-sqla07]
1011
basepython=python2.6
1112
deps=nose
13+
https://github.com/benthor/inflect.py/archive/master.zip#egg=inflect-0.2.3
1214
sqlalchemy<=0.7.99
1315

1416
[testenv:py26-sqla06]
1517
basepython=python2.6
1618
deps=nose
19+
https://github.com/benthor/inflect.py/archive/master.zip#egg=inflect-0.2.3
1720
sqlalchemy==0.6.0

0 commit comments

Comments
 (0)