Skip to content

Commit

Permalink
Add support for Django 3.x #135
Browse files Browse the repository at this point in the history
  • Loading branch information
r4fek committed Mar 9, 2020
1 parent 03cf102 commit c9d3674
Show file tree
Hide file tree
Showing 44 changed files with 580 additions and 490 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.idea/
.vscode/
.tox/
build/
dist/
Expand Down
18 changes: 18 additions & 0 deletions .isort.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[settings]
multi_line_output=3
force_grid_wrap=3
line_length=79
include_trailing_comma=True
known_first_party=django_cassandra_engine
known_third_party=
django,
furl,
icu,
ipcalc,
isoweek,
mock,
requests,
rest_framework,
from_first=True
combine_as_imports=True
force_to_top=False
43 changes: 27 additions & 16 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,36 +1,47 @@
dist: xenial
language: python
dist: bionic
sudo: required
services:
- cassandra

language: python
python:
- "3.7"

before_script:
- echo "deb http://www.apache.org/dist/cassandra/debian 40x main" | sudo tee -a /etc/apt/sources.list.d/cassandra.sources.list
- wget -qO - https://www.apache.org/dist/cassandra/KEYS | sudo apt-key add -
- sudo apt update
- sudo apt install cassandra
- sudo service cassandra start

env:
matrix:
- TOX_ENV=py27-django110
- TOX_ENV=py36-django110
- TOX_ENV=py27-django111
- TOX_ENV=py36-django111
- TOX_ENV=py36-django21
- TOX_ENV=py36-djangomaster
- TOX_ENV=py37-django21
- TOX_ENV=py37-django22
- TOX_ENV=py37-django30
- TOX_ENV=py37-djangomaster
global:
- CASS_DRIVER_NO_CYTHON=1
- CASS_HOST=127.0.0.1

python:
- "3.6"

addons:
apt:
packages:
- apt-transport-https
- build-essential
- python-dev
- python3-dev
- python3-pip
- pypy-dev
- libc-ares-dev
- libev4
- libev-dev
- sqlite3
- curl
- ca-certificates
- wget
- gnupg
- wait-for-it

install:
- pip install tox
- pip3 install tox-travis lz4

script:
- tox -e $TOX_ENV
- wait-for-it 127.0.0.1:9042 -- tox -e $TOX_ENV
8 changes: 6 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
FROM python:3.6
FROM python:3.7
ENV PYTHONUNBUFFERED=1
ENV CASS_HOST=cassandra
RUN apt-get -y update
RUN apt-get -y upgrade
RUN apt-get -y install wait-for-it

RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
ADD requirements-dev.txt /code/
RUN pip install -r requirements-dev.txt
ADD . /code/
RUN python setup.py develop
RUN pip3 install -e .

EXPOSE 8000
2 changes: 1 addition & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2014-2016, Rafał Furmański <[email protected]>
Copyright (c) 2014-2020, Rafał Furmański <[email protected]>
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ All tools you need to start your journey with Apache Cassandra and Django Framew
* working django forms
* usable admin panel with Cassandra models

## Plans (TODO) ##

* User model stored in Cassandra (auth module)

## Installation ##

Recommended installation:
Expand Down Expand Up @@ -80,6 +76,6 @@ If this project help you reduce time to develop, you can give me a cup of coffee
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/rrafek/5)

## License ##
Copyright (c) 2014-2018, [Rafał Furmański](https://rafal-furmanski.com).
Copyright (c) 2014-2020, [Rafał Furmański](https://linkedin.com/in/furmanski).

All rights reserved. Licensed under BSD 2-Clause License.
2 changes: 1 addition & 1 deletion django_cassandra_engine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-

# Do not forget to change version number in mkdocs.yml also!
__version__ = (1, 5, 5)
__version__ = (1, 6, 0)
__author__ = "Rafał Furmański"
__contact__ = "[email protected]"
__homepage__ = "http://github.com/r4fek/django-cassandra-engine"
Expand Down
6 changes: 3 additions & 3 deletions django_cassandra_engine/apps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import absolute_import, unicode_literals

import os

from django.apps import AppConfig as DjangoAppConfig
Expand Down Expand Up @@ -43,6 +41,7 @@ def __hash__(self):
def has_default(self):
return CallableBool(self.default is not None)


# monkey patch Column.has_default to be able to use function call too
columns.Column.has_default = property(has_default)

Expand All @@ -55,9 +54,10 @@ class AppConfig(DjangoAppConfig):

def connect(self):
from django_cassandra_engine.utils import get_cassandra_connections

for _, conn in get_cassandra_connections():
conn.connect()

def import_models(self, *args, **kwargs):
self.connect()
return super(AppConfig, self).import_models(*args, **kwargs)
return super().import_models(*args, **kwargs)
10 changes: 6 additions & 4 deletions django_cassandra_engine/base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
try:
from django.db.backends.base.base import (
connection_created,
BaseDatabaseWrapper
BaseDatabaseWrapper,
)
except ImportError:
try:
Expand Down Expand Up @@ -68,7 +68,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
'gt': '> %s',
'gte': '>= %s',
'lt': '< %s',
'lte': '<= %s'
'lte': '<= %s',
}

client = None
Expand Down Expand Up @@ -148,8 +148,10 @@ def _rollback(self):

def _cursor(self, *args, **kwargs):
keyspace = self.settings_dict['NAME']
if not self.connection.cluster.schema_metadata_enabled and \
keyspace not in self.connection.cluster.metadata.keyspaces:
if (
not self.connection.cluster.schema_metadata_enabled
and keyspace not in self.connection.cluster.metadata.keyspaces
):
self.connection.cluster.refresh_schema_metadata()

self.connection.cluster.metadata.keyspaces[keyspace]
Expand Down
6 changes: 1 addition & 5 deletions django_cassandra_engine/base/client.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import subprocess

import django
if django.VERSION[0:2] >= (1, 8):
from django.db.backends.base.client import BaseDatabaseClient
else:
from django.db.backends import BaseDatabaseClient
from django.db.backends.base.client import BaseDatabaseClient


class CassandraDatabaseClient(BaseDatabaseClient):
Expand Down
33 changes: 18 additions & 15 deletions django_cassandra_engine/base/creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,10 @@
from django_cassandra_engine.utils import get_default_cassandra_connection
from ..compat import create_keyspace_simple, drop_keyspace

if django.VERSION[0:2] >= (1, 8):
from django.db.backends.base.creation import BaseDatabaseCreation
else:
from django.db.backends.creation import BaseDatabaseCreation
from django.db.backends.base.creation import BaseDatabaseCreation


class CassandraDatabaseCreation(BaseDatabaseCreation):

def create_test_db(self, verbosity=1, autoclobber=False, **kwargs):
"""
Creates a test database, prompting the user for confirmation if the
Expand All @@ -27,19 +23,21 @@ def create_test_db(self, verbosity=1, autoclobber=False, **kwargs):
# If using django-nose, its runner has already set the db name
# to test_*, so restore it here so that all the models for the
# live keyspace can be found.
self.connection.connection.keyspace = \
self.connection.settings_dict['NAME']
self.connection.connection.keyspace = self.connection.settings_dict[
'NAME'
]
test_database_name = self._get_test_db_name()

# Set all models keyspace to the test keyspace
self.set_models_keyspace(test_database_name)

if verbosity >= 1:
test_db_repr = ''
if verbosity >= 2:
test_db_repr = " ('%s')" % test_database_name
print("Creating test database for alias '%s'%s..." % (
self.connection.alias, test_db_repr))
print(
"Creating test database for alias '%s'%s..."
% (self.connection.alias, test_db_repr)
)

options = self.connection.settings_dict.get('OPTIONS', {})

Expand All @@ -56,7 +54,8 @@ def create_test_db(self, verbosity=1, autoclobber=False, **kwargs):
create_keyspace_simple(
test_database_name,
replication_factor,
connections=[self.connection.alias])
connections=[self.connection.alias],
)

settings.DATABASES[self.connection.alias]["NAME"] = test_database_name
self.connection.settings_dict["NAME"] = test_database_name
Expand All @@ -70,14 +69,18 @@ def create_test_db(self, verbosity=1, autoclobber=False, **kwargs):
call_command(
'sync_cassandra',
verbosity=max(verbosity - 1, 0),
database=self.connection.alias
database=self.connection.alias,
)

# restore the original connection options
if not connection_options_copy.get('schema_metadata_enabled', True):
print('Disabling metadata on %s' % self.connection.settings_dict['NAME'])
options['connection']['schema_metadata_enabled'] = \
connection_options_copy['schema_metadata_enabled']
print(
'Disabling metadata on %s'
% self.connection.settings_dict['NAME']
)
options['connection'][
'schema_metadata_enabled'
] = connection_options_copy['schema_metadata_enabled']
self.connection.reconnect()
set_default_connection(default_alias)

Expand Down
12 changes: 2 additions & 10 deletions django_cassandra_engine/base/features.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
import django

if django.VERSION[0:2] >= (1, 8):
from django.db.backends.base.features import BaseDatabaseFeatures
else:
from django.db.backends import BaseDatabaseFeatures
from django.db.backends.base.features import BaseDatabaseFeatures


class CassandraDatabaseFeatures(BaseDatabaseFeatures):
string_based_auto_field = True
supports_long_model_names = False
supports_microsecond_precision = True
supports_transactions = False
can_rollback_ddl = True
uses_savepoints = False
requires_rollback_on_dirty_transaction = False
atomic_transactions = True

# Django 1.4 compatibility
def _supports_transactions(self):
return False

supports_transactions = _supports_transactions
35 changes: 21 additions & 14 deletions django_cassandra_engine/base/introspection.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
from itertools import chain

import django
if django.VERSION[0:2] >= (1, 8):
from django.db.backends.base.introspection import BaseDatabaseIntrospection
else:
from django.db.backends import BaseDatabaseIntrospection

from django.db.backends.base.introspection import BaseDatabaseIntrospection
from django_cassandra_engine.utils import get_installed_apps, get_cql_models


class CassandraDatabaseIntrospection(BaseDatabaseIntrospection):

def __init__(self, *args, **kwargs):

super(CassandraDatabaseIntrospection, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self._cql_models = {}
self._models_discovered = False

Expand All @@ -29,7 +22,8 @@ def _discover_models(self):

for app in apps:
self._cql_models[app.__name__] = get_cql_models(
app, connection=connection, keyspace=keyspace)
app, connection=connection, keyspace=keyspace
)

@property
def cql_models(self):
Expand All @@ -38,15 +32,23 @@ def cql_models(self):
self._models_discovered = True
return self._cql_models

def get_migratable_models(self):
return self.cql_models

def installed_models(self, tables):
return self.cql_models

def django_table_names(self, only_existing=False, **kwargs):
"""
Returns a list of all table names that have associated cqlengine models
and are present in settings.INSTALLED_APPS.
"""

all_models = list(chain.from_iterable(self.cql_models.values()))
tables = [model.column_family_name(include_keyspace=False)
for model in all_models]
tables = [
model.column_family_name(include_keyspace=False)
for model in all_models
]

return tables

Expand All @@ -60,8 +62,10 @@ def table_names(self, cursor=None, **kwargs):

connection = self.connection.connection
keyspace_name = connection.keyspace
if not connection.cluster.schema_metadata_enabled and \
keyspace_name not in connection.cluster.metadata.keyspaces:
if (
not connection.cluster.schema_metadata_enabled
and keyspace_name not in connection.cluster.metadata.keyspaces
):
connection.cluster.refresh_schema_metadata()

keyspace = connection.cluster.metadata.keyspaces[keyspace_name]
Expand All @@ -76,6 +80,9 @@ def sequence_list(self):
"""
return []

def get_sequences(self, *args, **kwargs):
return []

def get_relations(self, *_):
"""No relations in nonrel database"""
return []
Expand Down
Loading

0 comments on commit c9d3674

Please sign in to comment.