Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Ticket #77 (closed defect: fixed)

Opened 14 years ago

Last modified 12 years ago

[PATCH] Importing SQLObject classes into model.py doesn't work

Reported by: anonymous Owned by: anonymous
Priority: normal Milestone: 0.9
Component: SQLObject Version:
Severity: normal Keywords: develix
Cc: ianb@…

Description

I'm trying to import into model.py several modules, all located in the project package. I'm trying both class imports and package imports:

import user

as well as

from user import User

When I run tg-admin create sql, I'm getting:

... No classes found! No modules specified No packages specified Looked in eqqs: a2

The Getting Starting guide talks about being able to import into model.py, but I'm having a heck of a time actually doing it.


Here's an update. I think the Getting Started guide might be wrong on the ability to import other sql object classes as a way to distribute the model classes to other modules.

From the SQLObject docs:

"""When finding SQLObject classes, we look in the modules for classes that belong to the module -- so if you import a class from another module it won't be "matched". You have to indicate its original module."""

So, I added the modules to the egg info in sqlobjects.txt:

db_modules=foo.bar,baz.bam

and tq-admin sql create was able to find them.

Change History

comment:1 Changed 14 years ago by kevin

  • Milestone set to 0.9
  • Summary changed from Importing SQLObject classes into import.py doesn't work to Importing SQLObject classes into model.py doesn't work

I think Ian Bicking had a good reason why sqlobject-admin create ignores imported classes, but I can't find that message now :(

*Something* does need to happen here. Either the doc needs to be fixed or the code needs to be fixed.

comment:2 Changed 14 years ago by michele

The message Kevin was refering to is this:

 http://article.gmane.org/gmane.comp.python.sqlobject/4742

comment:3 Changed 14 years ago by ianb@…

I can't remember exactly why I made it like that. Something about wanting to make it predictable, but maybe that's not really accomplished well by this. I'll think about changing the semantics.

comment:4 Changed 13 years ago by elvelind@…

For now you can the soClasses variable in your model.py (or model/init.py) and specify the classes you want to use in a list.

comment:5 Changed 13 years ago by Luca <luca@…>

Maybe adding a flag to sqlobject-admin to select if you want to search recursively in the model or not could be a good choice: still easy to use and can be used any way you need it.

comment:6 Changed 13 years ago by Luca <luca@…>

  • Component changed from TurboGears to SQLObject

comment:7 Changed 13 years ago by kevin

  • Keywords develix added

comment:8 Changed 13 years ago by manxsupo@…

My vote would be to fix Getting Started Document with diff below:

Index: gettingstarted.html
===================================================================
--- gettingstarted.html (revision 573)
+++ gettingstarted.html (working copy)
@@ -525,7 +525,12 @@

     <p>You can also provide options via "query parameters" on the connection URI. A couple of useful options are debug and debugOutput. If you add ?debug=1 to your URI, each query will be output as it is run. If you add &amp;debugOutput=1, you'll also see the result of the query displayed.</p>

-    <p>You define your data model in the model.py module in your project's package. If you have more model code than will comfortably fit in one module, you can always break it up into multiple modules and import into the model module. SQLObject provides two different ways to define your database: you can define it in SQL directly in your database, or you can define it in Python. For clarity in your code, it is often easier to define your model in Python terms. If you <em>do</em> want your Python classes to be based on your database, you just do this:</p>
+    <p>You define your data model in the model.py module in your project's package. If you have more model code than will comfortably fit in one module, you can always break it up into multiple modules using one of the following two approaches:
+     <ol>
+      <li>Define a variable in your model.py or model/__init__.py module called 'soClasses' as a list of classes to include in the project's model.</li>
+      <li>Modify your projectName.egg-info/sqlobject.txt such that the db_module property is set to a comma delimited string of modules to find SQLObject persistable classes.</li>
+     </ol>
+SQLObject provides two different ways to define your database: you can define it in SQL directly in your database, or you can define it in Python. For clarity in your code, it is often easier to define your model in Python terms. If you <em>do</em> want your Python classes to be based on your database, you just do this:</p>

     <textarea name="code" class="py">
 from sqlobject import *

comment:9 Changed 13 years ago by jab@…

  • Status changed from new to assigned
  • Summary changed from Importing SQLObject classes into model.py doesn't work to [PATCH] Importing SQLObject classes into model.py doesn't work

The following is a SQLObject patch that adds an option to sqlobject.txt called "db_package". This tells sqlobject-admin to load all SQLObject classes found under the specified package. This was easy to do because the code for loading classes from packages was already there. I simply tweaked the code to support subpackages as well (i.e., package.subpackage).

In my project, I've tested this by having all model-related modules in project.lib.model and setting "db_package=project.lib.model". tg-admin successfully finds the SQLObject classes. Setting "db_package=project" works as well, though it is less efficient. There can be multiple packages separated with commas, as with db_module.

The patch allows both db_package and db_module to be specified, though allowing only one would be easy enough.


--- sqlobject/manager/command.py        2006-01-10 17:14:34.000000000 -0800
+++ sqlobject/manager/command.py        2006-01-23 18:34:19.000000000 -0800
@@ -372,6 +372,7 @@
         all = []
         package = moduleloader.load_module(package_name)
         package_dir = os.path.dirname(package.__file__)
+        package_subdir = package_name.replace('.', os.path.sep) + os.path.sep

         def find_classes_in_file(arg, dir_name, filenames):
             if dir_name.startswith('.svn'):
@@ -379,9 +380,9 @@
             filenames = filter(lambda fname: fname.endswith('.py') and fname != '__init__.py',
                                filenames)
             for fname in filenames:
-                module_name = os.path.join(dir_name, fname)
-                module_name = module_name[module_name.find(package_name):]
-                module_name = module_name.replace(os.path.sep,'.')[:-3]
+                module_dir = os.path.join(dir_name, fname)
+                module_subdir = module_dir[module_dir.rfind(os.path.sep + package_subdir):]
+                module_name = module_subdir.replace(os.path.sep,'.')[1:-3]
                 try:
                     module = moduleloader.load_module(module_name)
                 except ImportError, err:
@@ -401,6 +402,13 @@
     def classes_from_egg(self, egg_spec):
         modules = []
         dist, conf = self.config_from_egg(egg_spec, warn_no_sqlobject=True)
+        for pkg in conf.get('db_package', '').split(','):
+             pkg = pkg.strip()
+             if not pkg:
+                continue
+             if self.options.verbose:
+                 print 'Looking in package %s' % pkg
+             modules.extend(self.classes_from_package(pkg))
         for mod in conf.get('db_module', '').split(','):
             mod = mod.strip()
             if not mod:

comment:10 Changed 13 years ago by michele

Great, you should ping Ian Bicking for taking a look at this.

comment:11 Changed 13 years ago by jab@…

  • Cc ianb@… added

Ian, please check my patch.

comment:12 Changed 13 years ago by jorge.vargas

  • Status changed from assigned to closed
  • Resolution set to fixed

closing this is already in SO

Note: See TracTickets for help on using tickets.