Completed
Pull Request — develop (#143)
by
unknown
08:05
created

_instantiate()   A

Complexity

Conditions 3

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
c 2
b 0
f 0
dl 0
loc 8
ccs 6
cts 6
cp 1
crap 3
rs 9.4285
1
"""Functions to interact with mapped classes and instances."""
2
3 1
import inspect
4 1
import logging
5
import string
6 1
import glob
7
import types
8 1
9
from . import common, exceptions
10
11 1
log = logging.getLogger(__name__)
0 ignored issues
show
Coding Style Naming introduced by
The name log does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
12
13
14
def create(class_or_instance, *args, overwrite=False, **kwargs):
15
    """Create a new mapped object.
16
17 1
    NOTE: Calling this function is unnecessary with 'auto_create' enabled.
18 1
19
    """
20 1
    instance = _instantiate(class_or_instance, *args, **kwargs)
21 1
    mapper = common.get_mapper(instance, expected=True)
22 1
23
    if mapper.exists and not overwrite:
24 1
        msg = "{!r} already exists".format(mapper.path)
25
        raise exceptions.DuplicateMappingError(msg)
26
27 1
    return load(save(instance))
28
29 1
30 1
def find(class_or_instance, *args, create=False, **kwargs):  # pylint: disable=redefined-outer-name
0 ignored issues
show
introduced by
Locally disabling redefined-outer-name (W0621)
Loading history...
31
    """Find a matching mapped object or return None."""
32 1
    instance = _instantiate(class_or_instance, *args, **kwargs)
33 1
    mapper = common.get_mapper(instance, expected=True)
34 1
35 1
    if mapper.exists:
36
        return instance
37 1
    elif create:
38
        return save(instance)
39
    else:
40 1
        return None
41
42 1
43 1
class GlobFormatter(string.Formatter):
44
    """
45
    Uses '*' for all unknown fields
46 1
    """
47
48
    WILDCARD = object()
49
50
    def get_value(self, key, args, kwargs):
51
        try:
52
            return super().get_value(key, args, kwargs)
53 1
        except (KeyError, IndexError):
54
            return self.WILDCARD
55 1
56
    def convert_field(self, value, conversion):
57 1
        if value is self.WILDCARD:
58
            return self.WILDCARD
59
        else:
60 1
            return super().convert_field(value, conversion)
61
62
    def format_field(self, value, format_spec):
63
        if value is self.WILDCARD:
64
            return '*'
65
        else:
66 1
            return super().format_field(value, format_spec)
67
68 1
69 1
def match(cls, **kwargs):
70 1
    """Yield all matching mapped objects."""
71
    log.debug((cls, kwargs))
72 1
    gf = GlobFormatter()
0 ignored issues
show
Coding Style Naming introduced by
The name gf does not conform to the variable naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
73 1
    mock = types.SimpleNamespace(**kwargs)
74
75 1
    pattern = gf.format(..., self=mock)  # FIXME: Get the path_format given the class
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
Unused Code introduced by
Argument 'self' passed by position and keyword in method call
Loading history...
76
77 1
    for filename in glob.iglob(pattern, recursive=False):
0 ignored issues
show
Bug introduced by
The keyword recursive does not seem to exist for the function call.
Loading history...
78
        pathfields = {...: ...}  # FIXME: Extract the fields from the path (pypi:parse)
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
Unused Code introduced by
The variable pathfields seems to be unused.
Loading history...
79
        inst = cls(...)  # FIXME: Thaw class without invoking a bunch of stuff
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
80 1
        common.sync_object(inst, filename)
0 ignored issues
show
Bug introduced by
The Module yorm.common does not seem to have a member named sync_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...
81
        yield inst
82 1
83
84 1
def load(instance):
85
    """Force the loading of a mapped object's file.
86 1
87
    NOTE: Calling this function is unnecessary. It exists for the
88
        aesthetic purpose of having symmetry between save and load.
89 1
90 1
    """
91 1
    mapper = common.get_mapper(instance, expected=True)
92
93 1
    mapper.load()
94 1
95
    return instance
96 1
97
98
def save(instance):
99
    """Save a mapped object to file.
100
101
    NOTE: Calling this function is unnecessary with 'auto_save' enabled.
102
103
    """
104
    mapper = common.get_mapper(instance, expected=True)
105
106
    if mapper.deleted:
107
        msg = "{!r} was deleted".format(mapper.path)
108
        raise exceptions.DeletedFileError(msg)
109
110
    if not mapper.exists:
111
        mapper.create()
112
113
    mapper.save()
114
115
    return instance
116
117
118
def delete(instance):
119
    """Delete a mapped object's file."""
120
    mapper = common.get_mapper(instance, expected=True)
121
122
    mapper.delete()
123
124
    return None
125
126
127
def _instantiate(class_or_instance, *args, **kwargs):
0 ignored issues
show
Coding Style introduced by
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
128
    if inspect.isclass(class_or_instance):
129
        instance = class_or_instance(*args, **kwargs)
130
    else:
131
        assert not args
132
        instance = class_or_instance
133
134
    return instance
135