• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zopefoundation / Zope / 3956162881

pending completion
3956162881

push

github

Michael Howitz
Update to deprecation warning free releases.

4401 of 7036 branches covered (62.55%)

Branch coverage included in aggregate %.

27161 of 31488 relevant lines covered (86.26%)

0.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/App/Extensions.py
1
##############################################################################
2
#
3
# Copyright (c) 2002 Zope Foundation and Contributors.
4
#
5
# This software is subject to the provisions of the Zope Public License,
6
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
7
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10
# FOR A PARTICULAR PURPOSE
11
#
12
##############################################################################
13
"""Standard routines for handling extensions.
×
14

15
Extensions currently include external methods.
16
"""
17
import os
×
18
from functools import total_ordering
×
19

20
import Products
×
21
from zExceptions import NotFound
×
22

23

24
@total_ordering
×
25
class FuncCode:
×
26

27
    def __init__(self, f, im=0):
×
28
        self.co_varnames = f.__code__.co_varnames[im:]
×
29
        self.co_argcount = f.__code__.co_argcount - im
×
30

31
    def __eq__(self, other):
×
32
        if not isinstance(other, FuncCode):
×
33
            return False
×
34
        return (self.co_argcount, self.co_varnames) == \
×
35
               (other.co_argcount, other.co_varnames)
36

37
    def __lt__(self, other):
×
38
        if not isinstance(other, FuncCode):
×
39
            return False
×
40
        return (self.co_argcount, self.co_varnames) < \
×
41
               (other.co_argcount, other.co_varnames)
42

43

44
def _getPath(home, prefix, name, suffixes):
×
45

46
    dir = os.path.join(home, prefix)
×
47
    if dir == prefix:
×
48
        raise ValueError('The prefix, %s, should be a relative path' % prefix)
×
49

50
    fn = os.path.join(dir, name)
×
51
    if fn == name:
×
52
        # Paranoia
53
        raise ValueError(
×
54
            'The file name, %s, should be a simple file name' % name)
55

56
    for suffix in suffixes:
×
57
        if suffix:
×
58
            fqn = f"{fn}.{suffix}"
×
59
        else:
60
            fqn = fn
×
61
        if os.path.exists(fqn):
×
62
            return fqn
×
63

64

65
def getPath(prefix, name, checkProduct=1, suffixes=('',), cfg=None):
×
66
    """Find a file in one of several relative locations
67

68
    Arguments:
69

70
      prefix -- The location, relative to some home, to look for the
71
                file
72

73
      name -- The name of the file.  This must not be a path.
74

75
      checkProduct -- a flag indicating whether product directories
76
        should be used as additional hope ares to be searched. This
77
        defaults to a true value.
78

79
        If this is true and the name contains a dot, then the
80
        text before the dot is treated as a product name and
81
        the product package directory is used as anothe rhome.
82

83
      suffixes -- a sequences of file suffixes to check.
84
        By default, the name is used without a suffix.
85

86
      cfg -- ease testing (not part of the API)
87

88
    The search takes on multiple homes which are the instance home,
89
    the directory containing the directory containing the software
90
    home, and possibly product areas.
91
    """
92
    dir, ignored = os.path.split(name)
×
93
    if dir:
×
94
        raise ValueError(
×
95
            'The file name, %s, should be a simple file name' % name)
96

97
    if checkProduct:
×
98
        dot = name.find('.')
×
99
        if dot > 0:
×
100
            product = name[:dot]
×
101
            extname = name[dot + 1:]
×
102
            for product_dir in Products.__path__:
×
103
                found = _getPath(product_dir, os.path.join(product, prefix),
×
104
                                 extname, suffixes)
105
                if found is not None:
×
106
                    return found
×
107

108
    if cfg is None:
×
109
        import App.config
×
110
        cfg = App.config.getConfiguration()
×
111

112
    if prefix == "Extensions" and getattr(cfg, 'extensions', None) is not None:
×
113
        found = _getPath(cfg.extensions, '', name, suffixes)
×
114
        if found is not None:
×
115
            return found
×
116

117
    locations = [cfg.instancehome]
×
118

119
    for home in locations:
×
120
        found = _getPath(home, prefix, name, suffixes)
×
121
        if found is not None:
×
122
            return found
×
123

124
    try:
×
125
        dot = name.rfind('.')
×
126
        if dot > 0:
×
127
            realName = name[dot + 1:]
×
128
            toplevel = name[:dot]
×
129

130
            rdot = toplevel.rfind('.')
×
131
            if rdot > -1:
×
132
                module = __import__(
×
133
                    toplevel, globals(), {}, toplevel[rdot + 1:])
134
            else:
135
                module = __import__(toplevel)
×
136

137
            prefix = os.path.join(module.__path__[0], prefix, realName)
×
138

139
            for suffix in suffixes:
×
140
                if suffix:
×
141
                    fn = f"{prefix}.{suffix}"
×
142
                else:
143
                    fn = prefix
×
144
                if os.path.exists(fn):
×
145
                    return fn
×
146
    except Exception:
×
147
        pass
×
148

149

150
_modules = {}  # cache
×
151

152

153
def getObject(module, name, reload=0):
×
154
    # The use of _modules here is not thread safe, however, there is
155
    # no real harm in a race condition here.  If two threads
156
    # update the cache, then one will have simply worked a little
157
    # harder than need be.  So, in this case, we won't incur
158
    # the expense of a lock.
159
    old = _modules.get(module)
×
160
    if old is not None and name in old and not reload:
×
161
        return old[name]
×
162

163
    base, ext = os.path.splitext(module)
×
164
    if ext == 'py':
×
165
        # XXX should never happen; splitext() keeps '.' with the extension
166
        prefix = base
×
167
    else:
168
        prefix = module
×
169

170
    path = getPath('Extensions', prefix, suffixes=('', 'py'))
×
171
    if path is None:
×
172
        raise NotFound(
×
173
            "The specified module, '%s', couldn't be found." % module)
174

175
    __traceback_info__ = path, module
×
176

177
    try:
×
178
        with open(path) as f:
×
179
            execsrc = f.read()
×
180
    except Exception:
×
181
        raise NotFound("The specified module, '%s', "
×
182
                       "couldn't be opened." % module)
183
    module_dict = {}
×
184
    exec(execsrc, module_dict)
×
185

186
    if old is not None:
×
187
        # XXX Accretive??
188
        old.update(module_dict)
×
189
    else:
190
        _modules[module] = module_dict
×
191

192
    try:
×
193
        return module_dict[name]
×
194
    except KeyError:
×
195
        raise NotFound("The specified object, '%s', was not found "
×
196
                       "in module, '%s'." % (name, module))
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc