Passed
Pull Request — master (#24)
by
unknown
01:43
created

LocalizedFileField   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 75
Duplicated Lines 0 %

Test Coverage

Coverage 96.36%

Importance

Changes 4
Bugs 0 Features 1
Metric Value
wmc 24
c 4
b 0
f 1
dl 0
loc 75
ccs 53
cts 55
cp 0.9636
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A generate_filename() 0 9 2
A value_to_string() 0 7 3
A formfield() 0 6 2
A get_prep_value() 0 14 4
A __init__() 0 7 1
B save_form_data() 0 6 5
A deconstruct() 0 6 2
B pre_save() 0 8 5
1 1
import json
2 1
import datetime
3 1
import posixpath
4
5 1
from django.core.files import File
0 ignored issues
show
Configuration introduced by
The import django.core.files could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
6 1
from django.db.models.fields.files import FieldFile
0 ignored issues
show
Configuration introduced by
The import django.db.models.fields.files could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
7 1
from django.utils import six
0 ignored issues
show
Configuration introduced by
The import django.utils could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
8 1
from django.core.files.storage import default_storage
0 ignored issues
show
Configuration introduced by
The import django.core.files.storage could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
9 1
from django.utils.encoding import force_str, force_text
0 ignored issues
show
Configuration introduced by
The import django.utils.encoding could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
10
11 1
from localized_fields.fields import LocalizedField
12 1
from localized_fields.fields.field import LocalizedValueDescriptor
13 1
from localized_fields.value import LocalizedValue
14
15 1
from ..value import LocalizedFileValue
16 1
from ..forms import LocalizedFileFieldForm
17
18
19 1
class LocalizedFieldFile(FieldFile):
20
21 1
    def __init__(self, instance, field, name, lang):
22 1
        super().__init__(instance, field, name)
23 1
        self.lang = lang
24
25 1
    def save(self, name, content, save=True):
26 1
        name = self.field.generate_filename(self.instance, name, self.lang)
0 ignored issues
show
Bug introduced by
The Instance of LocalizedFieldFile does not seem to have a member named field.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
Bug introduced by
The Instance of LocalizedFieldFile does not seem to have a member named instance.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
27 1
        self.name = self.storage.save(name, content,
0 ignored issues
show
Bug introduced by
The Instance of LocalizedFieldFile does not seem to have a member named storage.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
Coding Style introduced by
The attribute name was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
28
                                      max_length=self.field.max_length)
0 ignored issues
show
Bug introduced by
The Instance of LocalizedFieldFile does not seem to have a member named field.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
29 1
        self._committed = True
0 ignored issues
show
Coding Style introduced by
The attribute _committed was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
30
31 1
        if save:
32 1
            self.instance.save()
0 ignored issues
show
Bug introduced by
The Instance of LocalizedFieldFile does not seem to have a member named instance.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
33
34 1
    save.alters_data = True
35
36 1
    def delete(self, save=True):
37 1
        if not self:
38 1
            return
39
40 1
        if hasattr(self, '_file'):
41 1
            self.close()
0 ignored issues
show
Bug introduced by
The Instance of LocalizedFieldFile does not seem to have a member named close.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
42 1
            del self.file
0 ignored issues
show
Bug introduced by
The Instance of LocalizedFieldFile does not seem to have a member named file.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
43
44 1
        self.storage.delete(self.name)
0 ignored issues
show
Bug introduced by
The Instance of LocalizedFieldFile does not seem to have a member named storage.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
45
46 1
        self.name = None
0 ignored issues
show
Coding Style introduced by
The attribute name was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
47 1
        self._committed = False
0 ignored issues
show
Coding Style introduced by
The attribute _committed was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
48
49 1
        if save:
50 1
            self.instance.save()
0 ignored issues
show
Bug introduced by
The Instance of LocalizedFieldFile does not seem to have a member named instance.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
51
52 1
    delete.alters_data = True
53
54
55 1
class LocalizedFileValueDescriptor(LocalizedValueDescriptor):
56 1
    def __get__(self, instance, cls=None):
57 1
        value = super().__get__(instance, cls)
58 1
        for lang, file in value.__dict__.items():
59 1
            if isinstance(file, six.string_types) or file is None:
60 1
                file = self.field.value_class(instance, self.field, file, lang)
61 1
                value.set(lang, file)
62
63 1
            elif isinstance(file, File) and \
64
                    not isinstance(file, LocalizedFieldFile):
65 1
                file_copy = self.field.value_class(instance, self.field,
66
                                                   file.name, lang)
67 1
                file_copy.file = file
68 1
                file_copy._committed = False
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _committed was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
69 1
                value.set(lang, file_copy)
70
71 1
            elif isinstance(file, LocalizedFieldFile) and \
72
                    not hasattr(file, 'field'):
73 1
                file.instance = instance
74 1
                file.field = self.field
75 1
                file.storage = self.field.storage
76 1
                file.lang = lang
77
78
            # Make sure that the instance is correct.
79 1
            elif isinstance(file, LocalizedFieldFile) \
80
                    and instance is not file.instance:
81 1
                file.instance = instance
82 1
                file.lang = lang
83 1
        return value
84
85
86 1
class LocalizedFileField(LocalizedField):
87 1
    descriptor_class = LocalizedFileValueDescriptor
88 1
    attr_class = LocalizedFileValue
89 1
    value_class = LocalizedFieldFile
90
91 1
    def __init__(self, verbose_name=None, name=None, upload_to='', storage=None,
92
                 **kwargs):
93
94 1
        self.storage = storage or default_storage
95 1
        self.upload_to = upload_to
96
97 1
        super().__init__(verbose_name, name, **kwargs)
98
99 1
    def deconstruct(self):
100 1
        name, path, args, kwargs = super().deconstruct()
101 1
        kwargs['upload_to'] = self.upload_to
102 1
        if self.storage is not default_storage:
103 1
            kwargs['storage'] = self.storage
104 1
        return name, path, args, kwargs
105
106 1
    def get_prep_value(self, value):
107
        """Returns field's value prepared for saving into a database."""
108
109 1
        if isinstance(value, LocalizedValue):
110 1
            prep_value = LocalizedValue()
111 1
            for k, v in value.__dict__.items():
112 1
                if v is None:
113 1
                    prep_value.set(k, '')
114
                else:
115
                    # Need to convert File objects provided via a form to
116
                    # unicode for database insertion
117 1
                    prep_value.set(k, six.text_type(v))
118 1
            return super().get_prep_value(prep_value)
119 1
        return super().get_prep_value(value)
120
121 1
    def pre_save(self, model_instance, add):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
122
        """Returns field's value just before saving."""
123 1
        value = super().pre_save(model_instance, add)
124 1
        if isinstance(value, LocalizedValue):
125 1
            for file in value.__dict__.values():
126 1
                if file and not file._committed:
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _committed was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
127 1
                    file.save(file.name, file, save=False)
128 1
        return value
129
130 1
    def generate_filename(self, instance, filename, lang):
131 1
        if callable(self.upload_to):
132 1
            filename = self.upload_to(instance, filename, lang)
133
        else:
134 1
            now = datetime.datetime.now()
135 1
            dirname = force_text(now.strftime(force_str(self.upload_to)))
136 1
            dirname = dirname.format(lang=lang)
137 1
            filename = posixpath.join(dirname, filename)
138 1
        return self.storage.generate_filename(filename)
139
140 1
    def save_form_data(self, instance, data):
141 1
        if isinstance(data, LocalizedValue):
142 1
            for k, v in data.__dict__.items():
143 1
                if v is not None and not v:
144 1
                    data.set(k, '')
145 1
            setattr(instance, self.name, data)
0 ignored issues
show
Bug introduced by
The Instance of LocalizedFileField does not seem to have a member named name.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
146
147 1
    def formfield(self, **kwargs):
148 1
        defaults = {'form_class': LocalizedFileFieldForm}
149 1
        if 'initial' in kwargs:
150
            defaults['required'] = False
151 1
        defaults.update(kwargs)
152 1
        return super().formfield(**defaults)
0 ignored issues
show
Coding Style introduced by
Usage of * or ** arguments should usually be done with care.

Generally, there is nothing wrong with usage of * or ** arguments. For readability of the code base, we suggest to not over-use these language constructs though.

For more information, we can recommend this blog post from Ned Batchelder including its comments which also touches this aspect.

Loading history...
153
154 1
    def value_to_string(self, obj):
155 1
        value = self.value_from_object(obj)
0 ignored issues
show
Bug introduced by
The Instance of LocalizedFileField does not seem to have a member named value_from_object.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
156 1
        if isinstance(value, LocalizedFileValue):
157 1
            return json.dumps({k: v.name for k, v
158
                               in value.__dict__.items()})
159
        else:
160
            return super().value_to_string(obj)
161