pyprocessors-iptc_mapper 0.5.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. pyprocessors_iptc_mapper-0.5.7/.gitignore +130 -0
  2. pyprocessors_iptc_mapper-0.5.7/.idea/.gitignore +8 -0
  3. pyprocessors_iptc_mapper-0.5.7/.idea/inspectionProfiles/Project_Default.xml +23 -0
  4. pyprocessors_iptc_mapper-0.5.7/.idea/inspectionProfiles/profiles_settings.xml +6 -0
  5. pyprocessors_iptc_mapper-0.5.7/.idea/misc.xml +7 -0
  6. pyprocessors_iptc_mapper-0.5.7/.idea/modules.xml +8 -0
  7. pyprocessors_iptc_mapper-0.5.7/.idea/pyprocessors_iptc_mapper.iml +15 -0
  8. pyprocessors_iptc_mapper-0.5.7/AUTHORS.md +5 -0
  9. pyprocessors_iptc_mapper-0.5.7/CHANGELOG.md +7 -0
  10. pyprocessors_iptc_mapper-0.5.7/Dockerfile +20 -0
  11. pyprocessors_iptc_mapper-0.5.7/Jenkinsfile +408 -0
  12. pyprocessors_iptc_mapper-0.5.7/LICENSE +21 -0
  13. pyprocessors_iptc_mapper-0.5.7/PKG-INFO +95 -0
  14. pyprocessors_iptc_mapper-0.5.7/README.md +48 -0
  15. pyprocessors_iptc_mapper-0.5.7/RELEASE.md +39 -0
  16. pyprocessors_iptc_mapper-0.5.7/bumpversion.py +41 -0
  17. pyprocessors_iptc_mapper-0.5.7/docs/.gitignore +2 -0
  18. pyprocessors_iptc_mapper-0.5.7/docs/CHANGELOG.md +7 -0
  19. pyprocessors_iptc_mapper-0.5.7/docs/LICENSE +21 -0
  20. pyprocessors_iptc_mapper-0.5.7/docs/_build/.buildinfo +4 -0
  21. pyprocessors_iptc_mapper-0.5.7/docs/_build/.doctrees/CHANGELOG.doctree +0 -0
  22. pyprocessors_iptc_mapper-0.5.7/docs/_build/.doctrees/environment.pickle +0 -0
  23. pyprocessors_iptc_mapper-0.5.7/docs/_build/.doctrees/index.doctree +0 -0
  24. pyprocessors_iptc_mapper-0.5.7/docs/_build/CHANGELOG.html +231 -0
  25. pyprocessors_iptc_mapper-0.5.7/docs/_build/LICENSE +21 -0
  26. pyprocessors_iptc_mapper-0.5.7/docs/_build/_modules/index.html +211 -0
  27. pyprocessors_iptc_mapper-0.5.7/docs/_build/_modules/pyformatters_consolidate/consolidate.html +304 -0
  28. pyprocessors_iptc_mapper-0.5.7/docs/_build/_sources/CHANGELOG.md.txt +7 -0
  29. pyprocessors_iptc_mapper-0.5.7/docs/_build/_sources/index.rst.txt +9 -0
  30. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/basic.css +904 -0
  31. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/badge_only.css +1 -0
  32. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
  33. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
  34. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
  35. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
  36. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/fontawesome-webfont.eot +0 -0
  37. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/fontawesome-webfont.svg +2671 -0
  38. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/fontawesome-webfont.ttf +0 -0
  39. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/fontawesome-webfont.woff +0 -0
  40. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
  41. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/lato-bold-italic.woff +0 -0
  42. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/lato-bold-italic.woff2 +0 -0
  43. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/lato-bold.woff +0 -0
  44. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/lato-bold.woff2 +0 -0
  45. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/lato-normal-italic.woff +0 -0
  46. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/lato-normal-italic.woff2 +0 -0
  47. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/lato-normal.woff +0 -0
  48. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/fonts/lato-normal.woff2 +0 -0
  49. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/css/theme.css +4 -0
  50. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/doctools.js +321 -0
  51. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/documentation_options.js +12 -0
  52. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/file.png +0 -0
  53. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Inconsolata-Bold.ttf +0 -0
  54. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Inconsolata-Regular.ttf +0 -0
  55. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Inconsolata.ttf +0 -0
  56. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-bold.eot +0 -0
  57. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-bold.ttf +0 -0
  58. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-bold.woff +0 -0
  59. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-bold.woff2 +0 -0
  60. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-bolditalic.eot +0 -0
  61. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-bolditalic.ttf +0 -0
  62. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-bolditalic.woff +0 -0
  63. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-bolditalic.woff2 +0 -0
  64. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-italic.eot +0 -0
  65. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-italic.ttf +0 -0
  66. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-italic.woff +0 -0
  67. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-italic.woff2 +0 -0
  68. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-regular.eot +0 -0
  69. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-regular.ttf +0 -0
  70. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-regular.woff +0 -0
  71. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato/lato-regular.woff2 +0 -0
  72. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato-Bold.ttf +0 -0
  73. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/Lato-Regular.ttf +0 -0
  74. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot +0 -0
  75. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf +0 -0
  76. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff +0 -0
  77. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 +0 -0
  78. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot +0 -0
  79. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf +0 -0
  80. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff +0 -0
  81. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 +0 -0
  82. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/RobotoSlab-Bold.ttf +0 -0
  83. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/RobotoSlab-Regular.ttf +0 -0
  84. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/fontawesome-webfont.eot +0 -0
  85. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/fontawesome-webfont.svg +2671 -0
  86. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/fontawesome-webfont.ttf +0 -0
  87. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/fontawesome-webfont.woff +0 -0
  88. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/fonts/fontawesome-webfont.woff2 +0 -0
  89. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/jquery-3.5.1.js +10872 -0
  90. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/jquery.js +2 -0
  91. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/js/badge_only.js +1 -0
  92. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/js/html5shiv-printshiv.min.js +4 -0
  93. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/js/html5shiv.min.js +4 -0
  94. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/js/modernizr.min.js +4 -0
  95. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/js/theme.js +1 -0
  96. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/jupyter-sphinx.css +123 -0
  97. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/language_data.js +297 -0
  98. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/minus.png +0 -0
  99. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/plus.png +0 -0
  100. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/pygments.css +74 -0
  101. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/searchtools.js +522 -0
  102. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/underscore-1.13.1.js +2042 -0
  103. pyprocessors_iptc_mapper-0.5.7/docs/_build/_static/underscore.js +6 -0
  104. pyprocessors_iptc_mapper-0.5.7/docs/_build/genindex.html +333 -0
  105. pyprocessors_iptc_mapper-0.5.7/docs/_build/index.html +262 -0
  106. pyprocessors_iptc_mapper-0.5.7/docs/_build/objects.inv +0 -0
  107. pyprocessors_iptc_mapper-0.5.7/docs/_build/py-modindex.html +235 -0
  108. pyprocessors_iptc_mapper-0.5.7/docs/_build/search.html +230 -0
  109. pyprocessors_iptc_mapper-0.5.7/docs/_build/searchindex.js +1 -0
  110. pyprocessors_iptc_mapper-0.5.7/docs/_static/.gitkeep +0 -0
  111. pyprocessors_iptc_mapper-0.5.7/docs/_templates/.gitkeep +0 -0
  112. pyprocessors_iptc_mapper-0.5.7/docs/conf.py +84 -0
  113. pyprocessors_iptc_mapper-0.5.7/docs/index.rst +9 -0
  114. pyprocessors_iptc_mapper-0.5.7/mypy.ini +6 -0
  115. pyprocessors_iptc_mapper-0.5.7/pyproject.toml +88 -0
  116. pyprocessors_iptc_mapper-0.5.7/results.xml +1 -0
  117. pyprocessors_iptc_mapper-0.5.7/setup.py +54 -0
  118. pyprocessors_iptc_mapper-0.5.7/src/pyprocessors_iptc_mapper/IPTC-MediaTopic-NewsCodes.xlsx +0 -0
  119. pyprocessors_iptc_mapper-0.5.7/src/pyprocessors_iptc_mapper/__init__.py +2 -0
  120. pyprocessors_iptc_mapper-0.5.7/src/pyprocessors_iptc_mapper/iptc_mapper.py +85 -0
  121. pyprocessors_iptc_mapper-0.5.7/tests/.coverage +0 -0
  122. pyprocessors_iptc_mapper-0.5.7/tests/__init__.py +0 -0
  123. pyprocessors_iptc_mapper-0.5.7/tests/data/x_cago_iptc_de-document-test.json +530 -0
  124. pyprocessors_iptc_mapper-0.5.7/tests/test_iptc_mapper.py +32 -0
  125. pyprocessors_iptc_mapper-0.5.7/tox.ini +49 -0
@@ -0,0 +1,130 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+ .idea/
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ *.py,cover
52
+ .hypothesis/
53
+ .pytest_cache/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ .python-version
87
+
88
+ # pipenv
89
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
90
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
91
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
92
+ # install all needed dependencies.
93
+ #Pipfile.lock
94
+
95
+ # celery beat schedule file
96
+ celerybeat-schedule
97
+
98
+ # SageMath parsed files
99
+ *.sage.py
100
+
101
+ # Environments
102
+ .env
103
+ .venv
104
+ env/
105
+ venv/
106
+ ENV/
107
+ env.bak/
108
+ venv.bak/
109
+
110
+ # Spyder project settings
111
+ .spyderproject
112
+ .spyproject
113
+
114
+ # Rope project settings
115
+ .ropeproject
116
+
117
+ # mkdocs documentation
118
+ /site
119
+
120
+ # mypy
121
+ .mypy_cache/
122
+ .dmypy.json
123
+ dmypy.json
124
+
125
+ # Pyre type checker
126
+ .pyre/
127
+
128
+ # Specific
129
+ .groovylintrc.json
130
+ .emailNotif
@@ -0,0 +1,8 @@
1
+ # Default ignored files
2
+ /shelf/
3
+ /workspace.xml
4
+ # Editor-based HTTP Client requests
5
+ /httpRequests/
6
+ # Datasource local storage ignored files
7
+ /dataSources/
8
+ /dataSources.local.xml
@@ -0,0 +1,23 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
5
+ <option name="ignoredErrors">
6
+ <list>
7
+ <option value="N806" />
8
+ <option value="N802" />
9
+ <option value="N803" />
10
+ <option value="N801" />
11
+ </list>
12
+ </option>
13
+ </inspection_tool>
14
+ <inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
15
+ <option name="ignoredIdentifiers">
16
+ <list>
17
+ <option value="pyformatters_mazars_table.mazars_table.CleanAndDeduplicate" />
18
+ <option value="pyformatters_mazars_table.mazars_table.*" />
19
+ </list>
20
+ </option>
21
+ </inspection_tool>
22
+ </profile>
23
+ </component>
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <settings>
3
+ <option name="USE_PROJECT_PROFILE" value="false" />
4
+ <version value="1.0" />
5
+ </settings>
6
+ </component>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="Black">
4
+ <option name="sdkName" value="Python 3.11 (whisperx)" />
5
+ </component>
6
+ <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8 virtualenv at /media/olivier/ssd1T/.pyenv/versions/pymultirole (2)" project-jdk-type="Python SDK" />
7
+ </project>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/pyprocessors_iptc_mapper.iml" filepath="$PROJECT_DIR$/.idea/pyprocessors_iptc_mapper.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="PYTHON_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$">
5
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
6
+ <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
7
+ </content>
8
+ <orderEntry type="jdk" jdkName="Python 3.8 virtualenv at /media/olivier/ssd1T/.pyenv/versions/pymultirole (2)" jdkType="Python SDK" />
9
+ <orderEntry type="sourceFolder" forTests="false" />
10
+ </component>
11
+ <component name="PyDocumentationSettings">
12
+ <option name="format" value="PLAIN" />
13
+ <option name="myDocStringFormat" value="Plain" />
14
+ </component>
15
+ </module>
@@ -0,0 +1,5 @@
1
+ # Authors
2
+
3
+ Contributors to pyprocessors_iptc_mapper include:
4
+
5
+ + [Olivier Terrier](mailto:olivier.terrier@kairntech.com)
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [unreleased]
@@ -0,0 +1,20 @@
1
+ FROM python:3.8-slim-buster
2
+ # Install prerequisites
3
+ RUN apt-get update -y && \
4
+ apt-get install -y \
5
+ patch \
6
+ gcc pkg-config \
7
+ libicu-dev && \
8
+ apt-get install -y --no-install-recommends \
9
+ g++ \
10
+ git && \
11
+ # Final upgrade + clean
12
+ apt-get update -y && \
13
+ apt-get clean all -y
14
+
15
+ # Enable Installing packages as root
16
+ ENV FLIT_ROOT_INSTALL=1
17
+
18
+ # Add pyproject.toml + README.md for flit install
19
+ ADD pyproject.toml pyproject.toml
20
+ ADD README.md README.md
@@ -0,0 +1,408 @@
1
+ pipeline {
2
+ environment {
3
+ PATH_HOME = '/home/jenkins'
4
+ TEST_REPORT_DIR = '/root/test-reports'
5
+ PYTHONPYCACHEPREFIX = '/tmp/.pytest_cache'
6
+ PYTHONDONTWRITEBYTECODE = '1'
7
+ JENKINS_UIDGID = '1004:1004'
8
+
9
+ MAJOR_VERSION = '0'
10
+ MINOR_VERSION = '5'
11
+ }
12
+
13
+ agent none
14
+
15
+ triggers {
16
+ upstream(upstreamProjects: 'pymultirole_plugins/' + BRANCH_NAME.replaceAll('/', '%2F'),\
17
+ threshold: hudson.model.Result.SUCCESS)
18
+ }
19
+
20
+ stages {
21
+ stage('Catch build termination') {
22
+ agent {
23
+ node {
24
+ label 'built-in'
25
+ customWorkspace "${PATH_HOME}/${JOB_NAME}"
26
+ }
27
+ }
28
+ stages {
29
+ stage('Analyse build cause') {
30
+ steps {
31
+ script {
32
+ analyseBuildCause()
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
38
+
39
+ stage('Generate new version') {
40
+ when {
41
+ environment name: 'SKIP_JOB', value: '0'
42
+ }
43
+
44
+ agent {
45
+ node {
46
+ label 'built-in'
47
+ customWorkspace "${PATH_HOME}/${JOB_NAME}"
48
+ }
49
+ }
50
+
51
+ stages {
52
+ stage('Add credentials') {
53
+ steps {
54
+ script {
55
+ // Add password file for flit publishing
56
+ sh "cp ${PATH_HOME}/.passwd-pypi .env"
57
+ }
58
+ }
59
+ }
60
+
61
+ stage('Commit new version') {
62
+ steps {
63
+ script {
64
+ println("attempt to publish ${JOB_NAME} with version: ${MAJOR_VERSION}.${MINOR_VERSION}.${BUILD_ID}")
65
+
66
+ // push updates of file __init__.py
67
+ withCredentials([gitUsernamePassword(credentialsId: 'bitbucket-user', gitToolName: 'git-tool')]) {
68
+ sh 'git pull'
69
+ sh "echo '\"\"\"Sherpa IPTC category mapper\"\"\"' > src/pyprocessors_iptc_mapper/__init__.py"
70
+ sh "echo '__version__ = \"${MAJOR_VERSION}.${MINOR_VERSION}.${env.BUILD_ID}\"' >> src/pyprocessors_iptc_mapper/__init__.py"
71
+ sh 'git commit src/pyprocessors_iptc_mapper/__init__.py -m "[Jenkins CI] Commit on version files" || echo "No changes to commit"'
72
+ sh 'git push'
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ stage('Build, test and publish') {
81
+ when {
82
+ beforeAgent true
83
+ environment name: 'SKIP_JOB', value: '0'
84
+ }
85
+
86
+ agent {
87
+ // dockerfile agent
88
+ // Mounted volume for Junit reports
89
+ // - docker: /root/test-reports
90
+ // - host : /tmp/_${JOB_NAME}/test-reports
91
+ dockerfile {
92
+ label 'built-in'
93
+ customWorkspace "${PATH_HOME}/${JOB_NAME}"
94
+ filename 'Dockerfile'
95
+ args "-u root --privileged -v /tmp/_${JOB_NAME}/test-reports:${TEST_REPORT_DIR}"
96
+ }
97
+ }
98
+
99
+ stages {
100
+ stage('Install flit & flake8') {
101
+ steps {
102
+ // remove any previous tox env
103
+ sh 'rm -rf .tox'
104
+ sh 'python -m pip install pip==22.0.3'
105
+ sh 'pip install --no-cache-dir flit==3.2.0 flake8==3.9.2 flakehell tox'
106
+ sh 'flit install'
107
+ }
108
+ }
109
+
110
+ stage('Test & lint python code') {
111
+ steps {
112
+ // remove any previous results.xml file
113
+ sh "rm -f ${TEST_REPORT_DIR}/results.xml"
114
+ sh 'tox'
115
+ }
116
+ }
117
+
118
+ stage('Publish on PyPI') {
119
+ environment {
120
+ FLIT_USERNAME = getUserName '.env'
121
+ FLIT_PASSWORD = getUserPass '.env'
122
+ }
123
+ steps {
124
+ // remove any previous folder dist
125
+ sh 'rm -rf dist'
126
+ // create (as root) folder dist
127
+ sh 'mkdir dist'
128
+ // pull recent updates of file __init__.py
129
+ withCredentials([gitUsernamePassword(credentialsId: 'bitbucket-user', gitToolName: 'git-tool')]) {
130
+ sh 'git config --global pull.rebase false'
131
+ sh "git config --global --add safe.directory ${WORKSPACE}"
132
+ sh 'git pull'
133
+ }
134
+ // put back owner of .git folder
135
+ sh "chown -R ${JENKINS_UIDGID} ${WORKSPACE}/.git"
136
+ // put back owner of pulled file
137
+ sh "chown ${JENKINS_UIDGID} src/pyprocessors_iptc_mapper/__init__.py"
138
+ // get git status
139
+ sh 'git status'
140
+ // publish on PyPI
141
+ sh '''
142
+ export COMMIT_VERSION=$( cat src/pyprocessors_iptc_mapper/__init__.py|grep version|cut -d '"' -f2|tr -s '[:blank:]' )
143
+ export BUILD_VERSION="${MAJOR_VERSION}"."${MINOR_VERSION}"."${BUILD_ID}"
144
+ if [ "${COMMIT_VERSION}" = "${BUILD_VERSION}" ] ; then flit publish ; fi
145
+ '''
146
+ // remove current folder dist
147
+ sh 'rm -rf dist'
148
+ // remove current folder .hypothesis
149
+ sh 'rm -rf .hypothesis'
150
+ // remove current folder .tox
151
+ sh 'rm -rf .tox'
152
+ }
153
+ }
154
+ }
155
+ }
156
+ }
157
+
158
+ post {
159
+ // only triggered when blue or green sign
160
+ success {
161
+ // node is specified here to get an agent
162
+ node('built-in') {
163
+ // keep using customWorkspace to store Junit report
164
+ ws("${PATH_HOME}/${JOB_NAME}") {
165
+ script {
166
+ try {
167
+ sh 'rm -f results.xml'
168
+ sh "cp /tmp/_${JOB_NAME}/test-reports/results.xml results.xml"
169
+ } catch (Exception e) {
170
+ println 'Exception occurred: ' + e.toString()
171
+ }
172
+ try {
173
+ junit 'results.xml'
174
+ } catch (Exception e) {
175
+ println 'Exception occurred: ' + e.toString()
176
+ }
177
+ if (sendEmailNotif("${PATH_HOME}/${JOB_NAME}", "${BUILD_NUMBER}")) {
178
+ println 'sending Success Build notification'
179
+ CUSTOM_SUBJECT = '[CI - Jenkinzz SUCCESS] ' + CUSTOM_SUBJECT
180
+ emailext(
181
+ mimeType: 'text/html',
182
+ subject: CUSTOM_SUBJECT,
183
+ body: '${DEFAULT_CONTENT}',
184
+ replyTo: '${DEFAULT_REPLYTO}',
185
+ to: '${ADMIN_RECIPIENTS}' + ';' + CUSTOM_RECIPIENTS
186
+ )
187
+ switchEmailNotif(false, BUILD_NUMBER)
188
+ } else {
189
+ println 'preventing Success Build notification'
190
+ }
191
+ }
192
+ }
193
+ }
194
+ }
195
+ // triggered when red sign
196
+ failure {
197
+ // node is specified here to get an agent
198
+ node('built-in') {
199
+ // keep using customWorkspace to store Junit report
200
+ ws("${PATH_HOME}/${JOB_NAME}") {
201
+ script {
202
+ try {
203
+ sh 'rm -f results.xml'
204
+ sh "cp /tmp/_${JOB_NAME}/test-reports/results.xml results.xml"
205
+ } catch (Exception e) {
206
+ println 'Exception occurred: ' + e.toString()
207
+ }
208
+ try {
209
+ junit 'results.xml'
210
+ } catch (Exception e) {
211
+ println 'Exception occurred: ' + e.toString()
212
+ }
213
+ println 'sending Failure Build notification'
214
+ CUSTOM_SUBJECT = '[CI - Jenkinzz FAILURE] ' + CUSTOM_SUBJECT
215
+ emailext(
216
+ mimeType: 'text/html',
217
+ subject: CUSTOM_SUBJECT,
218
+ body: '${DEFAULT_CONTENT}',
219
+ replyTo: '${DEFAULT_REPLYTO}',
220
+ to: '${ADMIN_RECIPIENTS}' + ';' + CUSTOM_RECIPIENTS
221
+ )
222
+ }
223
+ }
224
+ }
225
+ }
226
+ // triggered when black sign
227
+ aborted {
228
+ println 'post-declarative message: abort job'
229
+ }
230
+ // trigger every-works
231
+ //always {
232
+ //}
233
+ }
234
+ }
235
+
236
+ // return FLIT_USERNAME from given file
237
+ def getUserName(path) {
238
+ USERNAME = sh(
239
+ script: "grep FLIT_USERNAME ${path}|cut -d '=' -f2",
240
+ returnStdout: true
241
+ ).trim()
242
+ return USERNAME
243
+ }
244
+
245
+ // return FLIT_PASSWORD from given file
246
+ def getUserPass(path) {
247
+ USERPASS = sh(
248
+ script: "grep FLIT_PASSWORD ${path}|cut -d '=' -f2",
249
+ returnStdout: true
250
+ ).trim()
251
+ return USERPASS
252
+ }
253
+
254
+ // create/remove emailNotif file to trigger email notification
255
+ def switchEmailNotif(toggle, build) {
256
+ if (toggle) {
257
+ sh 'echo ' + build + ' > .emailNotif'
258
+ } else {
259
+ if (build == BUILD_NUMBER) {
260
+ sh 'rm -f .emailNotif'
261
+ }
262
+ }
263
+ }
264
+
265
+ // return true if emailNotif file present
266
+ boolean sendEmailNotif(path, build) {
267
+ emailNotif = sh(
268
+ script: "find ${path} -name '.emailNotif'|wc -l",
269
+ returnStdout: true
270
+ ).trim()
271
+ emailContent = ''
272
+ if (emailNotif == '1') {
273
+ emailContent = sh(
274
+ script: "cat ${path}/.emailNotif",
275
+ returnStdout: true
276
+ ).trim()
277
+ }
278
+ return (emailContent == build)
279
+ }
280
+
281
+ def analyseBuildCause() {
282
+ upstreamProjects = ['pyimporters_plugins']
283
+ boolean upstreamRunning = false
284
+ String jobName
285
+ // iterate over upstreamProjects
286
+ for (upstream_project in upstreamProjects) {
287
+ Jenkins.instance.getItemByFullName(upstream_project).items.each { repository ->
288
+ boolean isRunning = false
289
+ //repository.parent.name: project
290
+ //repository.name: branch
291
+ if ( repository.name == BRANCH_NAME ) {
292
+ // iterate over all jobs of current repository
293
+ repository.allJobs.each { job ->
294
+ // iterate over all builds of current job
295
+ job.builds.each { build ->
296
+ // determine if a build is running or not
297
+ if ( build.result == (null) ) {
298
+ jobName = build.parent.parent.name
299
+ isRunning = true
300
+ }
301
+ }
302
+ if ( isRunning ) {
303
+ upstreamRunning = true
304
+ }
305
+ }
306
+ }
307
+ }
308
+ }
309
+
310
+ // Catch if build has been triggered by CI Commit
311
+ // returnStatus = true when string not found -> Team commit
312
+ // returnStatus = false when string is found -> CI commit
313
+ boolean lastCommitIsTeam = sh(
314
+ script: 'git log -1 | grep "\\[Jenkins CI\\]"',
315
+ returnStatus: true
316
+ )
317
+
318
+ // Skip build when upstream detected
319
+ if (upstreamRunning) {
320
+ println 'Skipping build because upstream job detected (' + jobName + ')'
321
+ env.SKIP_JOB = '1'
322
+ switchEmailNotif(false, 0)
323
+ currentBuild.result = 'NOT_BUILT'
324
+ }
325
+
326
+ // Catch if build has been triggered by User
327
+ boolean isStartedByUser = currentBuild.rawBuild.getCause(hudson.model.Cause$UserIdCause) != null
328
+ if (isStartedByUser && !upstreamRunning) {
329
+ env.SKIP_JOB = '0'
330
+ env.CUSTOM_SUBJECT = JOB_NAME + ' - Manual Build #' + BUILD_NUMBER
331
+ env.CUSTOM_RECIPIENTS = emailextrecipients([[$class: 'RequesterRecipientProvider']])
332
+ switchEmailNotif(true, BUILD_NUMBER)
333
+ println 'Job started by User, proceeding'
334
+ }
335
+
336
+ // Catch if build has been triggered by Upstream
337
+ boolean isStartedByUpstream = currentBuild.rawBuild.getCause(hudson.model.Cause$UpstreamCause) != null
338
+ if (isStartedByUpstream && !upstreamRunning) {
339
+ int changeSetCount = 0
340
+ int ciSkipCount = 0
341
+ String upstreamFullJobName = ''
342
+ for (Run upstreamBuild : currentBuild.upstreamBuilds) {
343
+ upstreamFullJobName = upstreamBuild.rawBuild.fullDisplayName
344
+ if (upstreamBuild.changeSets != null) {
345
+ def changeLogSets = upstreamBuild.changeSets
346
+ for (int i = 0; i < changeLogSets.size(); i++) {
347
+ changeSetCount++
348
+ def entries = changeLogSets[i].items
349
+ for (int j = 0; j < entries.length; j++) {
350
+ def entry = entries[j]
351
+ if (entry.msg.contains('[Jenkins CI]')) {
352
+ ciSkipCount++
353
+ }
354
+ }
355
+ }
356
+ }
357
+ }
358
+ if (changeSetCount > 0 && changeSetCount == ciSkipCount) {
359
+ env.SKIP_JOB = '1'
360
+ switchEmailNotif(false, 0)
361
+ println 'Job started by Upstream [' + upstreamFullJobName + '], with CI commit, skipping'
362
+ currentBuild.result = 'NOT_BUILT'
363
+ } else {
364
+ env.SKIP_JOB = '0'
365
+ env.CUSTOM_SUBJECT = JOB_NAME + ' - Upstream Build #' + BUILD_NUMBER
366
+ env.CUSTOM_RECIPIENTS = emailextrecipients([[$class:'UpstreamComitterRecipientProvider']])
367
+ switchEmailNotif(true, BUILD_NUMBER)
368
+ println 'Job started by Upstream [' + upstreamFullJobName + '], proceeding'
369
+ }
370
+ }
371
+
372
+ // Catch if build has been triggered by User Commit
373
+ boolean isStartedByCommit = currentBuild.rawBuild.getCause(jenkins.branch.BranchEventCause) != null
374
+ if (isStartedByCommit && lastCommitIsTeam && !upstreamRunning) {
375
+ env.SKIP_JOB = '0'
376
+ env.CUSTOM_SUBJECT = JOB_NAME + ' - SCM Build #' + BUILD_NUMBER
377
+ env.CUSTOM_RECIPIENTS = emailextrecipients([[$class: 'DevelopersRecipientProvider'], [$class:'CulpritsRecipientProvider']])
378
+ switchEmailNotif(true, BUILD_NUMBER)
379
+ println 'Job started by User Commit, proceeding'
380
+ }
381
+
382
+ // Catch if build has been triggered by cron
383
+ boolean isStartedByCron = currentBuild.rawBuild.getCause(hudson.triggers.TimerTrigger$TimerTriggerCause) != null
384
+ if (isStartedByCron && lastCommitIsTeam && !upstreamRunning) {
385
+ env.SKIP_JOB = '0'
386
+ env.CUSTOM_SUBJECT = JOB_NAME + ' - CRON Build #' + BUILD_NUMBER
387
+ env.CUSTOM_RECIPIENTS = emailextrecipients([[$class: 'DevelopersRecipientProvider'], [$class:'CulpritsRecipientProvider']])
388
+ switchEmailNotif(true, BUILD_NUMBER)
389
+ println 'Job started by Cron, proceeding'
390
+ }
391
+
392
+ // Catch if build has been triggered by branch discovery
393
+ boolean isStartedByBranchDiscovery = currentBuild.rawBuild.getCause(jenkins.branch.BranchIndexingCause) != null
394
+ if (isStartedByBranchDiscovery && lastCommitIsTeam && !upstreamRunning) {
395
+ env.SKIP_JOB = '0'
396
+ env.CUSTOM_SUBJECT = JOB_NAME + ' - BranchDiscovery Build #' + BUILD_NUMBER
397
+ env.CUSTOM_RECIPIENTS = emailextrecipients([[$class: 'DevelopersRecipientProvider'], [$class:'CulpritsRecipientProvider']])
398
+ switchEmailNotif(true, BUILD_NUMBER)
399
+ println 'Job started by Branch Discovery, proceeding'
400
+ }
401
+
402
+ if (!lastCommitIsTeam && !upstreamRunning && !isStartedByUser && !isStartedByUpstream) {
403
+ println 'Skipping build because last commit has been done by CI'
404
+ env.SKIP_JOB = '1'
405
+ switchEmailNotif(false, 0)
406
+ //currentBuild.result = 'NOT_BUILT'
407
+ }
408
+ }
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Olivier Terrier
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.