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

inventree / InvenTree / 8535197168

03 Apr 2024 07:58AM UTC coverage: 90.342% (-2.2%) from 92.496%
8535197168

Pull #6881

github

web-flow
Merge a1722af93 into 6be2ede5e
Pull Request #6881: [PUI] Add coverage testing

227 of 631 branches covered (35.97%)

Branch coverage included in aggregate %.

0 of 1 new or added line in 1 file covered. (0.0%)

1 existing line in 1 file now uncovered.

31971 of 35009 relevant lines covered (91.32%)

1.12 hits per line

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

88.57
/src/backend/InvenTree/InvenTree/version.py
1
"""Version information for InvenTree.
2

3
Provides information on the current InvenTree version
4
"""
5

6
import os
1✔
7
import pathlib
1✔
8
import platform
1✔
9
import re
1✔
10
import sys
1✔
11
from datetime import datetime as dt
1✔
12
from datetime import timedelta as td
1✔
13

14
import django
1✔
15
from django.conf import settings
1✔
16

17
from dulwich.repo import NotGitRepository, Repo
1✔
18

19
from .api_version import INVENTREE_API_TEXT, INVENTREE_API_VERSION
1✔
20

21
# InvenTree software version
22
INVENTREE_SW_VERSION = '0.15.0 dev'
1✔
23

24
# Discover git
25
try:
1✔
26
    main_repo = Repo(pathlib.Path(__file__).parent.parent.parent.parent.parent)
1✔
27
    main_commit = main_repo[main_repo.head()]
1✔
28
except (NotGitRepository, FileNotFoundError):
×
29
    main_commit = None
×
30

31

32
def checkMinPythonVersion():
1✔
33
    """Check that the Python version is at least 3.9."""
34
    version = sys.version.split(' ')[0]
35
    docs = 'https://docs.inventree.org/en/stable/start/intro/#python-requirements'
36

37
    msg = f"""
38
    InvenTree requires Python 3.9 or above - you are running version {version}.
1✔
39
    - Refer to the InvenTree documentation for more information:
×
40
    - {docs}
1✔
41
    """
×
42

43
    if sys.version_info.major < 3:
1✔
44
        raise RuntimeError(msg)
×
45

46
    if sys.version_info.major == 3 and sys.version_info.minor < 9:
1✔
47
        raise RuntimeError(msg)
×
48

49
    print(f'Python version {version} - {sys.executable}')
1✔
50

51

52
def inventreeInstanceName():
1✔
53
    """Returns the InstanceName settings for the current database."""
54
    import common.models
55

56
    return common.models.InvenTreeSetting.get_setting('INVENTREE_INSTANCE', '')
57

58

59
def inventreeInstanceTitle():
60
    """Returns the InstanceTitle for the current database."""
61
    import common.models
1✔
62

63
    if common.models.InvenTreeSetting.get_setting('INVENTREE_INSTANCE_TITLE', False):
1✔
64
        return common.models.InvenTreeSetting.get_setting('INVENTREE_INSTANCE', '')
1✔
65
    return 'InvenTree'
1✔
66

67

68
def inventreeVersion():
1✔
69
    """Returns the InvenTree version string."""
70
    return INVENTREE_SW_VERSION.lower().strip()
71

72

73
def inventreeVersionTuple(version=None):
74
    """Return the InvenTree version string as (maj, min, sub) tuple."""
75
    if version is None:
1✔
76
        version = INVENTREE_SW_VERSION
1✔
77

78
    match = re.match(r'^.*(\d+)\.(\d+)\.(\d+).*$', str(version))
1✔
79

80
    return [int(g) for g in match.groups()]
1✔
81

82

83
def isInvenTreeDevelopmentVersion():
1✔
84
    """Return True if current InvenTree version is a "development" version."""
85
    return inventreeVersion().endswith('dev')
86

87

88
def inventreeDocsVersion():
89
    """Return the version string matching the latest documentation.
90

91
    Development -> "latest"
92
    Release -> "major.minor.sub" e.g. "0.5.2"
93
    """
94
    if isInvenTreeDevelopmentVersion():
1✔
95
        return 'latest'
1✔
96
    return INVENTREE_SW_VERSION  # pragma: no cover
×
97

98

99
def inventreeDocUrl():
1✔
100
    """Return URL for InvenTree documentation site."""
101
    tag = inventreeDocsVersion()
102
    return f'https://docs.inventree.org/en/{tag}'
103

104

105
def inventreeAppUrl():
106
    """Return URL for InvenTree app site."""
107
    return f'{inventreeDocUrl()}/app/app/'
1✔
108

109

110
def inventreeCreditsUrl():
1✔
111
    """Return URL for InvenTree credits site."""
112
    return 'https://docs.inventree.org/en/latest/credits/'
113

114

115
def inventreeGithubUrl():
116
    """Return URL for InvenTree github site."""
117
    return 'https://github.com/InvenTree/InvenTree/'
1✔
118

119

120
def isInvenTreeUpToDate():
1✔
121
    """Test if the InvenTree instance is "up to date" with the latest version.
122

123
    A background task periodically queries GitHub for latest version, and stores it to the database as "_INVENTREE_LATEST_VERSION"
124
    """
125
    import common.models
1✔
126

127
    latest = common.models.InvenTreeSetting.get_setting(
1✔
128
        '_INVENTREE_LATEST_VERSION', backup_value=None, create=False
1✔
129
    )
130

131
    # No record for "latest" version - we must assume we are up to date!
132
    if not latest:
1✔
133
        return True
1✔
134

135
    # Extract "tuple" version (Python can directly compare version tuples)
136
    latest_version = inventreeVersionTuple(latest)  # pragma: no cover
1✔
137
    inventree_version = inventreeVersionTuple()  # pragma: no cover
1✔
138

139
    return inventree_version >= latest_version  # pragma: no cover
1✔
140

141

142
def inventreeApiVersion():
1✔
143
    """Returns current API version of InvenTree."""
144
    return INVENTREE_API_VERSION
145

146

147
def parse_version_text():
148
    """Parse the version text to structured data."""
149
    patched_data = INVENTREE_API_TEXT.split('\n\n')
1✔
150
    # Remove first newline on latest version
151
    patched_data[0] = patched_data[0].replace('\n', '', 1)
1✔
152

153
    version_data = {}
1✔
154
    for version in patched_data:
1✔
155
        data = version.split('\n')
1✔
156

157
        version_split = data[0].split(' -> ')
1✔
158
        version_detail = (
1✔
159
            version_split[1].split(':', 1) if len(version_split) > 1 else ['']
1✔
160
        )
161
        new_data = {
1✔
162
            'version': version_split[0].strip(),
1✔
163
            'date': version_detail[0].strip(),
1✔
164
            'gh': version_detail[1].strip() if len(version_detail) > 1 else None,
1✔
165
            'text': data[1:],
1✔
166
            'latest': False,
1✔
167
        }
168
        version_data[new_data['version']] = new_data
1✔
169
    return version_data
1✔
170

171

172
INVENTREE_API_TEXT_DATA = parse_version_text()
1✔
173
"""Pre-processed API version text."""
×
174

175

176
def inventreeApiText(versions: int = 10, start_version: int = 0):
1✔
177
    """Returns API version descriptors.
178

179
    Args:
180
        versions: Number of versions to return. Default: 10
181
        start_version: first version to report. Defaults to return the latest {versions} versions.
182
    """
183
    version_data = INVENTREE_API_TEXT_DATA
1✔
184

185
    # Define the range of versions to return
186
    if start_version == 0:
1✔
187
        start_version = INVENTREE_API_VERSION - versions
1✔
188

189
    return {
1✔
190
        f'v{a}': version_data.get(f'v{a}', None)
1✔
191
        for a in range(start_version, start_version + versions)
1✔
192
    }
193

194

195
def inventreeDjangoVersion():
1✔
196
    """Returns the version of Django library."""
197
    return django.get_version()
198

199

200
def inventreePythonVersion():
201
    """Returns the version of python."""
202
    return sys.version.split(' ')[0]
1✔
203

204

205
def inventreeCommitHash():
1✔
206
    """Returns the git commit hash for the running codebase."""
207
    # First look in the environment variables, i.e. if running in docker
208
    commit_hash = os.environ.get('INVENTREE_COMMIT_HASH', '')
209

210
    if commit_hash:
211
        return commit_hash
212

213
    if main_commit is None:
214
        return None
215
    return main_commit.sha().hexdigest()[0:7]
216

217

218
def inventreeCommitDate():
219
    """Returns the git commit date for the running codebase."""
220
    # First look in the environment variables, e.g. if running in docker
221
    commit_date = os.environ.get('INVENTREE_COMMIT_DATE', '')
1✔
222

223
    if commit_date:
1✔
224
        return commit_date.split(' ')[0]
1✔
225

226
    if main_commit is None:
1✔
227
        return None
×
228

229
    commit_dt = dt.fromtimestamp(main_commit.commit_time) + td(
1✔
230
        seconds=main_commit.commit_timezone
1✔
231
    )
232
    return str(commit_dt.date())
1✔
233

234

235
def inventreeInstaller():
1✔
236
    """Returns the installer for the running codebase - if set."""
237
    # First look in the environment variables, e.g. if running in docker
238

239
    installer = os.environ.get('INVENTREE_PKG_INSTALLER', '')
240

241
    if installer:
242
        return installer
243
    elif settings.DOCKER:
244
        return 'DOC'
245
    elif main_commit is not None:
246
        return 'GIT'
247

248
    return None
249

250

251
def inventreeBranch():
252
    """Returns the branch for the running codebase - if set."""
253
    # First look in the environment variables, e.g. if running in docker
254

255
    branch = os.environ.get('INVENTREE_PKG_BRANCH', '')
1✔
256

257
    if branch:
1✔
258
        return branch
×
259

260
    if main_commit is None:
1✔
261
        return None
×
262

263
    try:
1✔
264
        branch = main_repo.refs.follow(b'HEAD')[0][1].decode()
1✔
UNCOV
265
        return branch.removeprefix('refs/heads/')
×
266
    except IndexError:
1✔
267
        return None  # pragma: no cover
1✔
268

269

270
def inventreeTarget():
1✔
271
    """Returns the target platform for the running codebase - if set."""
272
    # First look in the environment variables, e.g. if running in docker
273

274
    return os.environ.get('INVENTREE_PKG_TARGET', None)
275

276

277
def inventreePlatform():
278
    """Returns the platform for the instance."""
279
    return platform.platform(aliased=True)
1✔
280

281

282
def inventreeDatabase():
1✔
283
    """Return the InvenTree database backend e.g. 'postgresql'."""
284
    db = settings.DATABASES['default']
285
    return db.get('ENGINE', None).replace('django.db.backends.', '')
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