def fixture_dirs(self): """ Return a list of fixture directories. The list contains the 'fixtures' subdirectory of each installed application, if it exists, the directories in FIXTURE_DIRS, and the current directory. """ dirs = [] fixture_dirs = settings.FIXTURE_DIRS if len(fixture_dirs) != len(set(fixture_dirs)): raise ImproperlyConfigured( "settings.FIXTURE_DIRS contains duplicates.") for app_config in apps.get_app_configs(): app_label = app_config.label app_dir = os.path.join(app_config.path, 'fixtures') if app_dir in fixture_dirs: raise ImproperlyConfigured( "'%s' is a default fixture directory for the '%s' app " "and cannot be listed in settings.FIXTURE_DIRS." % (app_dir, app_label)) if self.app_label and app_label != self.app_label: continue if os.path.isdir(app_dir): dirs.append(app_dir) dirs.extend(list(fixture_dirs)) dirs.append('') dirs = [upath(os.path.abspath(os.path.realpath(d))) for d in dirs] return dirs
def _path_from_module(self, module): """Attempt to determine app's filesystem path from its module.""" # See #21874 for extended discussion of the behavior of this method in # various cases. # Convert paths to list because Python 3's _NamespacePath does not # support indexing. paths = list(getattr(module, '__path__', [])) if len(paths) != 1: filename = getattr(module, '__file__', None) if filename is not None: paths = [os.path.dirname(filename)] else: # For unknown reasons, sometimes the list returned by __path__ # contains duplicates that must be removed (#25246). paths = list(set(paths)) if len(paths) > 1: raise ImproperlyConfigured( "The app module %r has multiple filesystem locations (%r); " "you must configure this app with an AppConfig subclass " "with a 'path' class attribute." % (module, paths)) elif not paths: raise ImproperlyConfigured( "The app module %r has no filesystem location, " "you must configure this app with an AppConfig subclass " "with a 'path' class attribute." % (module, )) return upath(paths[0])
def get_connection_params(self): settings_dict = self.settings_dict if not settings_dict['NAME']: from arouse._dj.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured( "settings.DATABASES is improperly configured. " "Please supply the NAME value.") kwargs = { 'database': settings_dict['NAME'], 'detect_types': Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES, } kwargs.update(settings_dict['OPTIONS']) # Always allow the underlying SQLite connection to be shareable # between multiple threads. The safe-guarding will be handled at a # higher level by the `BaseDatabaseWrapper.allow_thread_sharing` # property. This is necessary as the shareability is disabled by # default in pysqlite and it cannot be changed once a connection is # opened. if 'check_same_thread' in kwargs and kwargs['check_same_thread']: warnings.warn( 'The `check_same_thread` option was provided and set to ' 'True. It will be overridden with False. Use the ' '`DatabaseWrapper.allow_thread_sharing` property instead ' 'for controlling thread shareability.', RuntimeWarning) kwargs.update({'check_same_thread': False}) if self.features.can_share_in_memory_db: kwargs.update({'uri': True}) return kwargs
def __init__(self, settings_module): # update this dict from global settings (but only for ALL_CAPS settings) for setting in dir(global_settings): if setting.isupper(): setattr(self, setting, getattr(global_settings, setting)) # store the settings module in case someone later cares self.SETTINGS_MODULE = settings_module mod = importlib.import_module(self.SETTINGS_MODULE) tuple_settings = ( "INSTALLED_APPS", "TEMPLATE_DIRS", "LOCALE_PATHS", ) self._explicit_settings = set() for setting in dir(mod): if setting.isupper(): setting_value = getattr(mod, setting) if (setting in tuple_settings and not isinstance(setting_value, (list, tuple))): raise ImproperlyConfigured("The %s setting must be a list or a tuple. " % setting) setattr(self, setting, setting_value) self._explicit_settings.add(setting) if not self.SECRET_KEY: raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.") if hasattr(time, 'tzset') and self.TIME_ZONE: # When we can, attempt to validate the timezone. If we can't find # this file, no check happens and it's harmless. zoneinfo_root = '/usr/share/zoneinfo' if (os.path.exists(zoneinfo_root) and not os.path.exists(os.path.join(zoneinfo_root, *(self.TIME_ZONE.split('/'))))): raise ValueError("Incorrect timezone setting: %s" % self.TIME_ZONE) # Move the time zone info into os.environ. See ticket #2315 for why # we don't do this unconditionally (breaks Windows). os.environ['TZ'] = self.TIME_ZONE time.tzset()
def _get_test_db_name(self): test_database_name = self.connection.settings_dict['TEST']['NAME'] can_share_in_memory_db = self.connection.features.can_share_in_memory_db if test_database_name and test_database_name != ':memory:': if 'mode=memory' in test_database_name and not can_share_in_memory_db: raise ImproperlyConfigured( "Using a shared memory database with `mode=memory` in the " "database name is not supported in your environment, " "use `:memory:` instead.") return test_database_name if can_share_in_memory_db: return 'file:memorydb_%s?mode=memory&cache=shared' % self.connection.alias return ':memory:'
def _setup_environment(environ): # Cygwin requires some special voodoo to set the environment variables # properly so that Oracle will see them. if platform.system().upper().startswith('CYGWIN'): try: import ctypes except ImportError as e: from arouse._dj.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured("Error loading ctypes: %s; " "the Oracle backend requires ctypes to " "operate correctly under Cygwin." % e) kernel32 = ctypes.CDLL('kernel32') for name, value in environ: kernel32.SetEnvironmentVariableA(name, value) else: os.environ.update(environ)
def _setup(self, name=None): """ Load the settings module pointed to by the environment variable. This is used the first time we need any settings at all, if the user has not previously configured the settings manually. """ settings_module = os.environ.get(ENVIRONMENT_VARIABLE) if not settings_module: desc = ("setting %s" % name) if name else "settings" raise ImproperlyConfigured( "Requested %s, but settings are not configured. " "You must either define the environment variable %s " "or call settings.configure() before accessing settings." % (desc, ENVIRONMENT_VARIABLE)) self._wrapped = Settings(settings_module)
def databases(self): if self._databases is None: self._databases = settings.DATABASES if self._databases == {}: self._databases = { DEFAULT_DB_ALIAS: { 'ENGINE': 'arouse._dj.db.backends.dummy', }, } if self._databases[DEFAULT_DB_ALIAS] == {}: self._databases[DEFAULT_DB_ALIAS][ 'ENGINE'] = 'arouse._dj.db.backends.dummy' if DEFAULT_DB_ALIAS not in self._databases: raise ImproperlyConfigured("You must define a '%s' database" % DEFAULT_DB_ALIAS) return self._databases
def prepare_sql_script(self, sql): """ Takes an SQL script that may contain multiple lines and returns a list of statements to feed to successive cursor.execute() calls. Since few databases are able to process raw SQL scripts in a single cursor.execute() call and PEP 249 doesn't talk about this use case, the default implementation is conservative. """ try: import sqlparse except ImportError: raise ImproperlyConfigured( "sqlparse is required if you don't split your SQL " "statements manually.") else: return [ sqlparse.format(statement, strip_comments=True) for statement in sqlparse.split(sql) if statement ]
def get_connection_params(self): settings_dict = self.settings_dict # None may be used to connect to the default 'postgres' db if settings_dict['NAME'] == '': raise ImproperlyConfigured( "settings.DATABASES is improperly configured. " "Please supply the NAME value.") conn_params = { 'database': settings_dict['NAME'] or 'postgres', } conn_params.update(settings_dict['OPTIONS']) conn_params.pop('isolation_level', None) if settings_dict['USER']: conn_params['user'] = settings_dict['USER'] if settings_dict['PASSWORD']: conn_params['password'] = force_str(settings_dict['PASSWORD']) if settings_dict['HOST']: conn_params['host'] = settings_dict['HOST'] if settings_dict['PORT']: conn_params['port'] = settings_dict['PORT'] return conn_params
def load_backend(backend_name): """ Return a database backend's "base" module given a fully qualified database backend name, or raise an error if it doesn't exist. """ # This backend was renamed in Django 1.9. if backend_name == 'arouse._dj.db.backends.postgresql_psycopg2': backend_name = 'arouse._dj.db.backends.postgresql' try: return import_module('%s.base' % backend_name) except ImportError as e_user: # The database backend wasn't found. Display a helpful error message # listing all possible (built-in) database backends. backend_dir = os.path.join(os.path.dirname(upath(__file__)), 'backends') try: builtin_backends = [ name for _, name, ispkg in pkgutil.iter_modules( [npath(backend_dir)]) if ispkg and name not in {'base', 'dummy', 'postgresql_psycopg2'} ] except EnvironmentError: builtin_backends = [] if backend_name not in [ 'arouse._dj.db.backends.%s' % b for b in builtin_backends ]: backend_reprs = map(repr, sorted(builtin_backends)) error_msg = ("%r isn't an available database backend.\n" "Try using 'arouse._dj.db.backends.XXX', where XXX " "is one of:\n %s\nError was: %s" % (backend_name, ", ".join(backend_reprs), e_user)) raise ImproperlyConfigured(error_msg) else: # If there's some other error, this must be an error in Django raise
def complain(*args, **kwargs): raise ImproperlyConfigured("settings.DATABASES is improperly configured. " "Please supply the ENGINE value. Check " "settings documentation for more details.")
from arouse._dj.utils.safestring import SafeBytes try: import pytz except ImportError: pytz = None try: try: from pysqlite2 import dbapi2 as Database except ImportError: from sqlite3 import dbapi2 as Database except ImportError as exc: from arouse._dj.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured( "Error loading either pysqlite2 or sqlite3 modules (tried in that order): %s" % exc) # Some of these import sqlite3, so import them after checking if it's installed. from .client import DatabaseClient # isort:skip from .creation import DatabaseCreation # isort:skip from .features import DatabaseFeatures # isort:skip from .introspection import DatabaseIntrospection # isort:skip from .operations import DatabaseOperations # isort:skip from .schema import DatabaseSchemaEditor # isort:skip DatabaseError = Database.DatabaseError IntegrityError = Database.IntegrityError def adapt_datetime_warn_on_aware_datetime(value):
def __setattr__(self, name, value): if name in ("MEDIA_URL", "STATIC_URL") and value and not value.endswith('/'): raise ImproperlyConfigured("If set, %s must end with a slash" % name) object.__setattr__(self, name, value)
from arouse._dj.conf import settings from arouse._dj.db import utils from arouse._dj.db.backends import utils as backend_utils from arouse._dj.db.backends.base.base import BaseDatabaseWrapper from arouse._dj.utils import six, timezone from arouse._dj.utils.deprecation import RemovedInDjango20Warning from arouse._dj.utils.encoding import force_str from arouse._dj.utils.functional import cached_property from arouse._dj.utils.safestring import SafeBytes, SafeText try: import MySQLdb as Database except ImportError as e: from arouse._dj.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured("Error loading MySQLdb module: %s" % e) from MySQLdb.constants import CLIENT, FIELD_TYPE # isort:skip from MySQLdb.converters import Thing2Literal, conversions # isort:skip # Some of these import MySQLdb, so import them after checking if it's installed. from .client import DatabaseClient # isort:skip from .creation import DatabaseCreation # isort:skip from .features import DatabaseFeatures # isort:skip from .introspection import DatabaseIntrospection # isort:skip from .operations import DatabaseOperations # isort:skip from .schema import DatabaseSchemaEditor # isort:skip from .validation import DatabaseValidation # isort:skip # We want version (1, 2, 1, 'final', 2) or later. We can't just use # lexicographic ordering in this check because then (1, 2, 1, 'gamma')
def populate(self, installed_apps=None): """ Loads application configurations and models. This method imports each application module and then each model module. It is thread safe and idempotent, but not reentrant. """ if self.ready: return # populate() might be called by two threads in parallel on servers # that create threads before initializing the WSGI callable. with self._lock: if self.ready: return # app_config should be pristine, otherwise the code below won't # guarantee that the order matches the order in INSTALLED_APPS. if self.app_configs: raise RuntimeError("populate() isn't reentrant") # Load app configs and app modules. for entry in installed_apps: if isinstance(entry, AppConfig): app_config = entry else: app_config = AppConfig.create(entry) if app_config.label in self.app_configs: raise ImproperlyConfigured( "Application labels aren't unique, " "duplicates: %s" % app_config.label) self.app_configs[app_config.label] = app_config # Check for duplicate app names. counts = Counter(app_config.name for app_config in self.app_configs.values()) duplicates = [ name for name, count in counts.most_common() if count > 1 ] if duplicates: raise ImproperlyConfigured("Application names aren't unique, " "duplicates: %s" % ", ".join(duplicates)) self.apps_ready = True # Load models. for app_config in self.app_configs.values(): all_models = self.all_models[app_config.label] app_config.import_models(all_models) self.clear_cache() self.models_ready = True for app_config in self.get_app_configs(): app_config.ready() self.ready = True
from arouse._dj.conf import settings from arouse._dj.core.exceptions import ImproperlyConfigured from arouse._dj.db import DEFAULT_DB_ALIAS from arouse._dj.db.backends.base.base import BaseDatabaseWrapper from arouse._dj.db.backends.base.validation import BaseDatabaseValidation from arouse._dj.db.utils import DatabaseError as WrappedDatabaseError from arouse._dj.utils.encoding import force_str from arouse._dj.utils.functional import cached_property from arouse._dj.utils.safestring import SafeBytes, SafeText try: import psycopg2 as Database import psycopg2.extensions import psycopg2.extras except ImportError as e: raise ImproperlyConfigured("Error loading psycopg2 module: %s" % e) def psycopg2_version(): version = psycopg2.__version__.split(' ', 1)[0] return tuple(int(v) for v in version.split('.') if v.isdigit()) PSYCOPG2_VERSION = psycopg2_version() if PSYCOPG2_VERSION < (2, 4, 5): raise ImproperlyConfigured( "psycopg2_version 2.4.5 or newer is required; you have %s" % psycopg2.__version__) # Some of these import psycopg2, so import them after checking if it's installed.
def create(cls, entry): """ Factory that creates an app config from an entry in INSTALLED_APPS. """ try: # If import_module succeeds, entry is a path to an app module, # which may specify an app config class with default_app_config. # Otherwise, entry is a path to an app config class or an error. module = import_module(entry) except ImportError: # Track that importing as an app module failed. If importing as an # app config class fails too, we'll trigger the ImportError again. module = None mod_path, _, cls_name = entry.rpartition('.') # Raise the original exception when entry cannot be a path to an # app config class. if not mod_path: raise else: try: # If this works, the app module specifies an app config class. entry = module.default_app_config except AttributeError: # Otherwise, it simply uses the default app config class. return cls(entry, module) else: mod_path, _, cls_name = entry.rpartition('.') # If we're reaching this point, we must attempt to load the app config # class located at <mod_path>.<cls_name> mod = import_module(mod_path) try: cls = getattr(mod, cls_name) except AttributeError: if module is None: # If importing as an app module failed, that error probably # contains the most informative traceback. Trigger it again. import_module(entry) else: raise # Check for obvious errors. (This check prevents duck typing, but # it could be removed if it became a problem in practice.) if not issubclass(cls, AppConfig): raise ImproperlyConfigured("'%s' isn't a subclass of AppConfig." % entry) # Obtain app name here rather than in AppClass.__init__ to keep # all error checking for entries in INSTALLED_APPS in one place. try: app_name = cls.name except AttributeError: raise ImproperlyConfigured("'%s' must supply a name attribute." % entry) # Ensure app_name points to a valid module. app_module = import_module(app_name) # Entry is a path to an app config class. return cls(app_name, app_module)
def _require_pytz(self): if settings.USE_TZ and pytz is None: raise ImproperlyConfigured("This query requires pytz, but it isn't installed.")
os.environ.update(environ) _setup_environment([ # Oracle takes client-side character set encoding from the environment. ('NLS_LANG', '.UTF8'), # This prevents unicode from getting mangled by getting encoded into the # potentially non-unicode database character set. ('ORA_NCHAR_LITERAL_REPLACE', 'TRUE'), ]) try: import cx_Oracle as Database except ImportError as e: from arouse._dj.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured("Error loading cx_Oracle module: %s" % e) # Some of these import cx_Oracle, so import them after checking if it's installed. from .client import DatabaseClient # NOQA isort:skip from .creation import DatabaseCreation # NOQA isort:skip from .features import DatabaseFeatures # NOQA isort:skip from .introspection import DatabaseIntrospection # NOQA isort:skip from .operations import DatabaseOperations # NOQA isort:skip from .schema import DatabaseSchemaEditor # NOQA isort:skip from .utils import Oracle_datetime, convert_unicode # NOQA isort:skip DatabaseError = Database.DatabaseError IntegrityError = Database.IntegrityError class _UninitializedOperatorsDescriptor(object):