eea.api.redirector 0.1__tar.gz → 0.2__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 (181) hide show
  1. {eea_api_redirector-0.1/eea.api.redirector.egg-info → eea_api_redirector-0.2}/PKG-INFO +42 -15
  2. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/README.rst +23 -1
  3. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/docs/HISTORY.txt +18 -13
  4. eea_api_redirector-0.2/eea/api/redirector/locales/bg/LC_MESSAGES/eea.mo +0 -0
  5. eea_api_redirector-0.2/eea/api/redirector/locales/bg/LC_MESSAGES/plone.mo +0 -0
  6. eea_api_redirector-0.2/eea/api/redirector/locales/cs/LC_MESSAGES/eea.mo +0 -0
  7. eea_api_redirector-0.2/eea/api/redirector/locales/cs/LC_MESSAGES/plone.mo +0 -0
  8. eea_api_redirector-0.2/eea/api/redirector/locales/da/LC_MESSAGES/eea.mo +0 -0
  9. eea_api_redirector-0.2/eea/api/redirector/locales/da/LC_MESSAGES/plone.mo +0 -0
  10. eea_api_redirector-0.2/eea/api/redirector/locales/de/LC_MESSAGES/eea.mo +0 -0
  11. eea_api_redirector-0.2/eea/api/redirector/locales/de/LC_MESSAGES/plone.mo +0 -0
  12. eea_api_redirector-0.2/eea/api/redirector/locales/el/LC_MESSAGES/eea.mo +0 -0
  13. eea_api_redirector-0.2/eea/api/redirector/locales/el/LC_MESSAGES/plone.mo +0 -0
  14. eea_api_redirector-0.2/eea/api/redirector/locales/en/LC_MESSAGES/eea.mo +0 -0
  15. eea_api_redirector-0.2/eea/api/redirector/locales/en/LC_MESSAGES/plone.mo +0 -0
  16. eea_api_redirector-0.2/eea/api/redirector/locales/es/LC_MESSAGES/eea.mo +0 -0
  17. eea_api_redirector-0.2/eea/api/redirector/locales/es/LC_MESSAGES/plone.mo +0 -0
  18. eea_api_redirector-0.2/eea/api/redirector/locales/et/LC_MESSAGES/eea.mo +0 -0
  19. eea_api_redirector-0.2/eea/api/redirector/locales/et/LC_MESSAGES/plone.mo +0 -0
  20. eea_api_redirector-0.2/eea/api/redirector/locales/eu/LC_MESSAGES/eea.mo +0 -0
  21. eea_api_redirector-0.2/eea/api/redirector/locales/eu/LC_MESSAGES/plone.mo +0 -0
  22. eea_api_redirector-0.2/eea/api/redirector/locales/fi/LC_MESSAGES/eea.mo +0 -0
  23. eea_api_redirector-0.2/eea/api/redirector/locales/fi/LC_MESSAGES/plone.mo +0 -0
  24. eea_api_redirector-0.2/eea/api/redirector/locales/fr/LC_MESSAGES/eea.mo +0 -0
  25. eea_api_redirector-0.2/eea/api/redirector/locales/fr/LC_MESSAGES/plone.mo +0 -0
  26. eea_api_redirector-0.2/eea/api/redirector/locales/hr/LC_MESSAGES/eea.mo +0 -0
  27. eea_api_redirector-0.2/eea/api/redirector/locales/hr/LC_MESSAGES/plone.mo +0 -0
  28. eea_api_redirector-0.2/eea/api/redirector/locales/hu/LC_MESSAGES/eea.mo +0 -0
  29. eea_api_redirector-0.2/eea/api/redirector/locales/hu/LC_MESSAGES/plone.mo +0 -0
  30. eea_api_redirector-0.2/eea/api/redirector/locales/is/LC_MESSAGES/eea.mo +0 -0
  31. eea_api_redirector-0.2/eea/api/redirector/locales/is/LC_MESSAGES/plone.mo +0 -0
  32. eea_api_redirector-0.2/eea/api/redirector/locales/it/LC_MESSAGES/eea.mo +0 -0
  33. eea_api_redirector-0.2/eea/api/redirector/locales/it/LC_MESSAGES/plone.mo +0 -0
  34. eea_api_redirector-0.2/eea/api/redirector/locales/kl/LC_MESSAGES/eea.mo +0 -0
  35. eea_api_redirector-0.2/eea/api/redirector/locales/kl/LC_MESSAGES/plone.mo +0 -0
  36. eea_api_redirector-0.2/eea/api/redirector/locales/lt/LC_MESSAGES/eea.mo +0 -0
  37. eea_api_redirector-0.2/eea/api/redirector/locales/lt/LC_MESSAGES/plone.mo +0 -0
  38. eea_api_redirector-0.2/eea/api/redirector/locales/lv/LC_MESSAGES/eea.mo +0 -0
  39. eea_api_redirector-0.2/eea/api/redirector/locales/lv/LC_MESSAGES/plone.mo +0 -0
  40. eea_api_redirector-0.2/eea/api/redirector/locales/mt/LC_MESSAGES/eea.mo +0 -0
  41. eea_api_redirector-0.2/eea/api/redirector/locales/mt/LC_MESSAGES/plone.mo +0 -0
  42. eea_api_redirector-0.2/eea/api/redirector/locales/nl/LC_MESSAGES/eea.mo +0 -0
  43. eea_api_redirector-0.2/eea/api/redirector/locales/nl/LC_MESSAGES/plone.mo +0 -0
  44. eea_api_redirector-0.2/eea/api/redirector/locales/no/LC_MESSAGES/eea.mo +0 -0
  45. eea_api_redirector-0.2/eea/api/redirector/locales/no/LC_MESSAGES/plone.mo +0 -0
  46. eea_api_redirector-0.2/eea/api/redirector/locales/pl/LC_MESSAGES/eea.mo +0 -0
  47. eea_api_redirector-0.2/eea/api/redirector/locales/pl/LC_MESSAGES/plone.mo +0 -0
  48. eea_api_redirector-0.2/eea/api/redirector/locales/pt/LC_MESSAGES/eea.mo +0 -0
  49. eea_api_redirector-0.2/eea/api/redirector/locales/pt/LC_MESSAGES/plone.mo +0 -0
  50. eea_api_redirector-0.2/eea/api/redirector/locales/pt_BR/LC_MESSAGES/eea.mo +0 -0
  51. eea_api_redirector-0.2/eea/api/redirector/locales/pt_BR/LC_MESSAGES/plone.mo +0 -0
  52. eea_api_redirector-0.2/eea/api/redirector/locales/ro/LC_MESSAGES/eea.mo +0 -0
  53. eea_api_redirector-0.2/eea/api/redirector/locales/ro/LC_MESSAGES/plone.mo +0 -0
  54. eea_api_redirector-0.2/eea/api/redirector/locales/ru/LC_MESSAGES/eea.mo +0 -0
  55. eea_api_redirector-0.2/eea/api/redirector/locales/ru/LC_MESSAGES/plone.mo +0 -0
  56. eea_api_redirector-0.2/eea/api/redirector/locales/sk/LC_MESSAGES/eea.mo +0 -0
  57. eea_api_redirector-0.2/eea/api/redirector/locales/sk/LC_MESSAGES/plone.mo +0 -0
  58. eea_api_redirector-0.2/eea/api/redirector/locales/sl/LC_MESSAGES/eea.mo +0 -0
  59. eea_api_redirector-0.2/eea/api/redirector/locales/sl/LC_MESSAGES/plone.mo +0 -0
  60. eea_api_redirector-0.2/eea/api/redirector/locales/sv/LC_MESSAGES/eea.mo +0 -0
  61. eea_api_redirector-0.2/eea/api/redirector/locales/sv/LC_MESSAGES/plone.mo +0 -0
  62. eea_api_redirector-0.2/eea/api/redirector/locales/tr/LC_MESSAGES/eea.mo +0 -0
  63. eea_api_redirector-0.2/eea/api/redirector/locales/tr/LC_MESSAGES/plone.mo +0 -0
  64. eea_api_redirector-0.2/eea/api/redirector/locales/zh_TW/LC_MESSAGES/eea.mo +0 -0
  65. eea_api_redirector-0.2/eea/api/redirector/locales/zh_TW/LC_MESSAGES/plone.mo +0 -0
  66. eea_api_redirector-0.2/eea/api/redirector/restapi/add.py +122 -0
  67. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/restapi/configure.zcml +9 -0
  68. eea_api_redirector-0.2/eea/api/redirector/restapi/import_csv.py +89 -0
  69. eea_api_redirector-0.2/eea/api/redirector/version.txt +1 -0
  70. {eea_api_redirector-0.1 → eea_api_redirector-0.2/eea.api.redirector.egg-info}/PKG-INFO +42 -15
  71. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea.api.redirector.egg-info/SOURCES.txt +63 -0
  72. eea_api_redirector-0.1/eea/api/redirector/restapi/add.py +0 -115
  73. eea_api_redirector-0.1/eea/api/redirector/version.txt +0 -1
  74. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/CONTRIBUTING.md +0 -0
  75. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/MANIFEST.in +0 -0
  76. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/docs/LICENSE.GPL +0 -0
  77. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/docs/LICENSE.txt +0 -0
  78. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/__init__.py +0 -0
  79. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/__init__.py +0 -0
  80. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/README.txt +0 -0
  81. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/__init__.py +0 -0
  82. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/browser/__init__.py +0 -0
  83. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/browser/configure.zcml +0 -0
  84. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/browser/controlpanel.py +0 -0
  85. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/configure.zcml +0 -0
  86. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/interfaces.py +0 -0
  87. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/__init__.py +0 -0
  88. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/bg/LC_MESSAGES/eea.po +0 -0
  89. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/bg/LC_MESSAGES/plone.po +0 -0
  90. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/cs/LC_MESSAGES/eea.po +0 -0
  91. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/cs/LC_MESSAGES/plone.po +0 -0
  92. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/da/LC_MESSAGES/eea.po +0 -0
  93. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/da/LC_MESSAGES/plone.po +0 -0
  94. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/de/LC_MESSAGES/eea.po +0 -0
  95. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/de/LC_MESSAGES/plone.po +0 -0
  96. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/eea.pot +0 -0
  97. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/el/LC_MESSAGES/eea.po +0 -0
  98. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/el/LC_MESSAGES/plone.po +0 -0
  99. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/en/LC_MESSAGES/eea.po +0 -0
  100. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/en/LC_MESSAGES/plone.po +0 -0
  101. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/es/LC_MESSAGES/eea.po +0 -0
  102. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/es/LC_MESSAGES/plone.po +0 -0
  103. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/et/LC_MESSAGES/eea.po +0 -0
  104. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/et/LC_MESSAGES/plone.po +0 -0
  105. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/eu/LC_MESSAGES/eea.po +0 -0
  106. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/eu/LC_MESSAGES/plone.po +0 -0
  107. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/fi/LC_MESSAGES/eea.po +0 -0
  108. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/fi/LC_MESSAGES/plone.po +0 -0
  109. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/fr/LC_MESSAGES/eea.po +0 -0
  110. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/fr/LC_MESSAGES/plone.po +0 -0
  111. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/hr/LC_MESSAGES/eea.po +0 -0
  112. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/hr/LC_MESSAGES/plone.po +0 -0
  113. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/hu/LC_MESSAGES/eea.po +0 -0
  114. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/hu/LC_MESSAGES/plone.po +0 -0
  115. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/is/LC_MESSAGES/eea.po +0 -0
  116. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/is/LC_MESSAGES/plone.po +0 -0
  117. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/it/LC_MESSAGES/eea.po +0 -0
  118. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/it/LC_MESSAGES/plone.po +0 -0
  119. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/kl/LC_MESSAGES/eea.po +0 -0
  120. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/kl/LC_MESSAGES/plone.po +0 -0
  121. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/lt/LC_MESSAGES/eea.po +0 -0
  122. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/lt/LC_MESSAGES/plone.po +0 -0
  123. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/lv/LC_MESSAGES/eea.po +0 -0
  124. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/lv/LC_MESSAGES/plone.po +0 -0
  125. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/mt/LC_MESSAGES/eea.po +0 -0
  126. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/mt/LC_MESSAGES/plone.po +0 -0
  127. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/nl/LC_MESSAGES/eea.po +0 -0
  128. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/nl/LC_MESSAGES/plone.po +0 -0
  129. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/no/LC_MESSAGES/eea.po +0 -0
  130. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/no/LC_MESSAGES/plone.po +0 -0
  131. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/pl/LC_MESSAGES/eea.po +0 -0
  132. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/pl/LC_MESSAGES/plone.po +0 -0
  133. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/plone-manual.pot +0 -0
  134. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/pt/LC_MESSAGES/eea.po +0 -0
  135. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/pt/LC_MESSAGES/plone.po +0 -0
  136. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/pt_BR/LC_MESSAGES/eea.po +0 -0
  137. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/pt_BR/LC_MESSAGES/plone.po +0 -0
  138. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/ro/LC_MESSAGES/eea.po +0 -0
  139. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/ro/LC_MESSAGES/plone.po +0 -0
  140. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/ru/LC_MESSAGES/eea.po +0 -0
  141. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/ru/LC_MESSAGES/plone.po +0 -0
  142. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/sk/LC_MESSAGES/eea.po +0 -0
  143. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/sk/LC_MESSAGES/plone.po +0 -0
  144. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/sl/LC_MESSAGES/eea.po +0 -0
  145. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/sl/LC_MESSAGES/plone.po +0 -0
  146. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/sv/LC_MESSAGES/eea.po +0 -0
  147. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/sv/LC_MESSAGES/plone.po +0 -0
  148. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/tr/LC_MESSAGES/eea.po +0 -0
  149. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/tr/LC_MESSAGES/plone.po +0 -0
  150. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/update.sh +0 -0
  151. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/zh_TW/LC_MESSAGES/eea.po +0 -0
  152. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/locales/zh_TW/LC_MESSAGES/plone.po +0 -0
  153. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/profiles/default/browserlayer.xml +0 -0
  154. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/profiles/default/controlpanel.xml +0 -0
  155. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/profiles/default/metadata.xml +0 -0
  156. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/profiles/default/registry.xml +0 -0
  157. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/profiles/uninstall/browserlayer.xml +0 -0
  158. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/profiles.zcml +0 -0
  159. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/restapi/__init__.py +0 -0
  160. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/restapi/controlpanel.py +0 -0
  161. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/restapi/delete.py +0 -0
  162. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/restapi/get.py +0 -0
  163. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/restapi/statistics.py +0 -0
  164. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/setuphandlers.py +0 -0
  165. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/tests/__init__.py +0 -0
  166. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/tests/base.py +0 -0
  167. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/tests/test_doctests.py +0 -0
  168. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/upgrades/__init__.py +0 -0
  169. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/upgrades/configure.zcml +0 -0
  170. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/utilities/__init__.py +0 -0
  171. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/utilities/configure.zcml +0 -0
  172. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/utilities/errors.py +0 -0
  173. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea/api/redirector/utilities/storage.py +0 -0
  174. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea.api.redirector.egg-info/dependency_links.txt +0 -0
  175. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea.api.redirector.egg-info/entry_points.txt +0 -0
  176. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea.api.redirector.egg-info/namespace_packages.txt +0 -0
  177. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea.api.redirector.egg-info/not-zip-safe +0 -0
  178. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea.api.redirector.egg-info/requires.txt +0 -0
  179. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/eea.api.redirector.egg-info/top_level.txt +0 -0
  180. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/setup.cfg +0 -0
  181. {eea_api_redirector-0.1 → eea_api_redirector-0.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eea.api.redirector
3
- Version: 0.1
3
+ Version: 0.2
4
4
  Summary: Plone Redirector extension to get redirect URLs also from Redis
5
5
  Home-page: https://github.com/eea/eea.api.redirector
6
6
  Author: European Environment Agency: IDM2 A-Team
@@ -61,7 +61,8 @@ Main features
61
61
  9. **Proper HTTP status codes**: Returns 410 Gone for permanently deleted resources (empty redirect targets)
62
62
  10. **Redirect loop prevention**: Built-in protection against circular redirects
63
63
  11. **Easy configuration**: Simple environment variable setup for Redis connections
64
- 12. **Non-intrusive**: Extends existing Plone functionality without replacing it
64
+ 12. **CSV import endpoint**: Upload CSV files directly to the backend for bulk imports
65
+ 13. **Non-intrusive**: Extends existing Plone functionality without replacing it
65
66
 
66
67
 
67
68
  Install
@@ -236,6 +237,27 @@ Response::
236
237
  "failed": []
237
238
  }
238
239
 
240
+ **POST /@redirects-import**
241
+
242
+ Import redirects from a CSV file upload.
243
+
244
+ Request:
245
+
246
+ * Multipart form-data with ``file`` field containing the CSV file
247
+
248
+ Example::
249
+
250
+ curl -u admin:admin -F "file=@redirects.csv" http://localhost:8080/Plone/@redirects-import
251
+
252
+ Response::
253
+
254
+ {
255
+ "type": "success",
256
+ "success_count": 10,
257
+ "failed_count": 0,
258
+ "failed": []
259
+ }
260
+
239
261
 
240
262
  Performance
241
263
  ===========
@@ -321,32 +343,37 @@ EEA_ - European Environment Agency (EU)
321
343
  Changelog
322
344
  =========
323
345
 
346
+ 0.2 - (2025-12-20)
347
+ ------------------------
348
+ * Feature: CSV import endpoint (@redirects-import) for server-side processing
349
+ [avoinea - refs #293748]
350
+
324
351
  0.1 - (2025-11-28)
325
352
  -----------------------
326
353
 
327
354
  * Feature: Redis-backed URL redirects with high-performance lookups
328
- [avoinea - refs $293748]
355
+ [avoinea - refs #293748]
329
356
  * Feature: REST API endpoints (@redirects, @redirects-statistics) for full CRUD operations
330
- [avoinea - refs $293748]
357
+ [avoinea - refs #293748]
331
358
  * Feature: Advanced search with regex support and search scope selector (old_url, new_url, both)
332
- [avoinea - refs $293748]
359
+ [avoinea - refs #293748]
333
360
  * Feature: HTTP 410 Gone support for permanently deleted content (empty redirect targets)
334
- [avoinea - refs $293748]
361
+ [avoinea - refs #293748]
335
362
  * Feature: High-performance statistics using Redis pipelining (~2s for 100k+ redirects)
336
- [avoinea - refs $293748]
363
+ [avoinea - refs #293748]
337
364
  * Feature: Pagination support with configurable batch sizes (10, 25, 50, 100, 500, 1000)
338
- [avoinea - refs $293748]
365
+ [avoinea - refs #293748]
339
366
  * Feature: Alphabetical sorting of redirects for consistent display
340
- [avoinea - refs $293748]
367
+ [avoinea - refs #293748]
341
368
  * Feature: Bulk import/export via REST API (CSV support in frontend)
342
- [avoinea - refs $293748]
369
+ [avoinea - refs #293748]
343
370
  * Feature: Fallback mechanism to check Redis when redirects not found in Plone storage
344
- [avoinea - refs $293748]
371
+ [avoinea - refs #293748]
345
372
  * Feature: Graceful error handling - Redis failures don't break redirection system
346
- [avoinea - refs $293748]
373
+ [avoinea - refs #293748]
347
374
  * Feature: API endpoint support with intelligent hierarchical URL matching
348
- [avoinea - refs $293748]
375
+ [avoinea - refs #293748]
349
376
  * Feature: Redirect loop prevention
350
- [avoinea - refs $293748]
377
+ [avoinea - refs #293748]
351
378
  * Feature: Easy configuration via environment variables (REDIS_SERVER, REDIS_PORT, REDIS_DB, REDIS_TIMEOUT)
352
- [avoinea - refs $293748]
379
+ [avoinea - refs #293748]
@@ -27,7 +27,8 @@ Main features
27
27
  9. **Proper HTTP status codes**: Returns 410 Gone for permanently deleted resources (empty redirect targets)
28
28
  10. **Redirect loop prevention**: Built-in protection against circular redirects
29
29
  11. **Easy configuration**: Simple environment variable setup for Redis connections
30
- 12. **Non-intrusive**: Extends existing Plone functionality without replacing it
30
+ 12. **CSV import endpoint**: Upload CSV files directly to the backend for bulk imports
31
+ 13. **Non-intrusive**: Extends existing Plone functionality without replacing it
31
32
 
32
33
 
33
34
  Install
@@ -202,6 +203,27 @@ Response::
202
203
  "failed": []
203
204
  }
204
205
 
206
+ **POST /@redirects-import**
207
+
208
+ Import redirects from a CSV file upload.
209
+
210
+ Request:
211
+
212
+ * Multipart form-data with ``file`` field containing the CSV file
213
+
214
+ Example::
215
+
216
+ curl -u admin:admin -F "file=@redirects.csv" http://localhost:8080/Plone/@redirects-import
217
+
218
+ Response::
219
+
220
+ {
221
+ "type": "success",
222
+ "success_count": 10,
223
+ "failed_count": 0,
224
+ "failed": []
225
+ }
226
+
205
227
 
206
228
  Performance
207
229
  ===========
@@ -1,32 +1,37 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 0.2 - (2025-12-20)
5
+ ------------------------
6
+ * Feature: CSV import endpoint (@redirects-import) for server-side processing
7
+ [avoinea - refs #293748]
8
+
4
9
  0.1 - (2025-11-28)
5
10
  -----------------------
6
11
 
7
12
  * Feature: Redis-backed URL redirects with high-performance lookups
8
- [avoinea - refs $293748]
13
+ [avoinea - refs #293748]
9
14
  * Feature: REST API endpoints (@redirects, @redirects-statistics) for full CRUD operations
10
- [avoinea - refs $293748]
15
+ [avoinea - refs #293748]
11
16
  * Feature: Advanced search with regex support and search scope selector (old_url, new_url, both)
12
- [avoinea - refs $293748]
17
+ [avoinea - refs #293748]
13
18
  * Feature: HTTP 410 Gone support for permanently deleted content (empty redirect targets)
14
- [avoinea - refs $293748]
19
+ [avoinea - refs #293748]
15
20
  * Feature: High-performance statistics using Redis pipelining (~2s for 100k+ redirects)
16
- [avoinea - refs $293748]
21
+ [avoinea - refs #293748]
17
22
  * Feature: Pagination support with configurable batch sizes (10, 25, 50, 100, 500, 1000)
18
- [avoinea - refs $293748]
23
+ [avoinea - refs #293748]
19
24
  * Feature: Alphabetical sorting of redirects for consistent display
20
- [avoinea - refs $293748]
25
+ [avoinea - refs #293748]
21
26
  * Feature: Bulk import/export via REST API (CSV support in frontend)
22
- [avoinea - refs $293748]
27
+ [avoinea - refs #293748]
23
28
  * Feature: Fallback mechanism to check Redis when redirects not found in Plone storage
24
- [avoinea - refs $293748]
29
+ [avoinea - refs #293748]
25
30
  * Feature: Graceful error handling - Redis failures don't break redirection system
26
- [avoinea - refs $293748]
31
+ [avoinea - refs #293748]
27
32
  * Feature: API endpoint support with intelligent hierarchical URL matching
28
- [avoinea - refs $293748]
33
+ [avoinea - refs #293748]
29
34
  * Feature: Redirect loop prevention
30
- [avoinea - refs $293748]
35
+ [avoinea - refs #293748]
31
36
  * Feature: Easy configuration via environment variables (REDIS_SERVER, REDIS_PORT, REDIS_DB, REDIS_TIMEOUT)
32
- [avoinea - refs $293748]
37
+ [avoinea - refs #293748]
@@ -0,0 +1,122 @@
1
+ """RestAPI endpoint @redirects POST"""
2
+
3
+ from plone.restapi.deserializer import json_body
4
+ from plone.restapi.services import Service
5
+ from zExceptions import BadRequest
6
+ from zope.component import getUtility
7
+ from zope.interface import alsoProvides
8
+ from zope.interface import implementer
9
+ from zope.publisher.interfaces import IPublishTraverse
10
+ from eea.api.redirector.interfaces import IStorageUtility
11
+ import plone.protect.interfaces
12
+ import logging
13
+
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ def add_redirects(storage, redirects):
19
+ """Validate and add redirects to storage."""
20
+ failed_redirects = []
21
+ success_count = 0
22
+
23
+ for redirect in redirects:
24
+ if not isinstance(redirect, dict):
25
+ failed_redirects.append(
26
+ {
27
+ "redirect": str(redirect),
28
+ "error": "Item must be a dictionary with 'path' and 'redirect-to' keys",
29
+ }
30
+ )
31
+ continue
32
+
33
+ path = redirect.get("path")
34
+ target = redirect.get("redirect-to")
35
+
36
+ if not path:
37
+ failed_redirects.append(
38
+ {"redirect": str(redirect), "error": "Missing 'path' field"}
39
+ )
40
+ continue
41
+
42
+ if target is None:
43
+ failed_redirects.append(
44
+ {"redirect": str(redirect), "error": "Missing 'redirect-to' field"}
45
+ )
46
+ continue
47
+
48
+ # Validate paths
49
+ if not path.startswith("/"):
50
+ failed_redirects.append(
51
+ {
52
+ "redirect": str(redirect),
53
+ "error": f"Path must start with '/': {path}",
54
+ }
55
+ )
56
+ continue
57
+
58
+ # Prevent self-redirects (but allow empty target for Gone)
59
+ if target and path == target:
60
+ failed_redirects.append(
61
+ {
62
+ "redirect": str(redirect),
63
+ "error": "Path and target cannot be the same",
64
+ }
65
+ )
66
+ continue
67
+
68
+ # Add to Redis
69
+ try:
70
+ result = storage.set(path, target)
71
+ if result:
72
+ success_count += 1
73
+ logger.info("Added redirect: %s -> %s", path, target)
74
+ else:
75
+ failed_redirects.append(
76
+ {
77
+ "path": path,
78
+ "redirect-to": target,
79
+ "error": "Failed to set value in Redis",
80
+ }
81
+ )
82
+ except Exception as err:
83
+ logger.exception("Error adding redirect %s -> %s: %s", path, target, err)
84
+ failed_redirects.append(
85
+ {"path": path, "redirect-to": target, "error": str(err)}
86
+ )
87
+
88
+ return success_count, failed_redirects
89
+
90
+
91
+ @implementer(IPublishTraverse)
92
+ class RedisRedirectsPost(Service):
93
+ """Add redirects to Redis"""
94
+
95
+ def reply(self):
96
+ """Add one or more redirects to Redis storage"""
97
+ # Disable CSRF protection
98
+ if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
99
+ alsoProvides(self.request, plone.protect.interfaces.IDisableCSRFProtection)
100
+
101
+ data = json_body(self.request)
102
+ storage = getUtility(IStorageUtility)
103
+ redirects = data.get("items", [])
104
+
105
+ if not redirects:
106
+ raise BadRequest(
107
+ "No items provided. Expected format: {'items': [{'path': '/old', 'redirect-to': '/new'}]}"
108
+ )
109
+
110
+ success_count, failed_redirects = add_redirects(storage, redirects)
111
+
112
+ # Return appropriate response
113
+ if failed_redirects:
114
+ self.request.response.setStatus(207) # Multi-Status
115
+ return {
116
+ "type": "partial_success" if success_count > 0 else "error",
117
+ "success_count": success_count,
118
+ "failed_count": len(failed_redirects),
119
+ "failed": failed_redirects,
120
+ }
121
+
122
+ return self.reply_no_content()
@@ -37,6 +37,15 @@
37
37
  permission="cmf.ManagePortal"
38
38
  />
39
39
 
40
+ <!-- POST endpoint to import Redis redirects from CSV -->
41
+ <plone:service
42
+ method="POST"
43
+ name="@redirects-import"
44
+ for="Products.CMFCore.interfaces.ISiteRoot"
45
+ factory=".import_csv.RedisRedirectsCSVImport"
46
+ permission="cmf.ManagePortal"
47
+ />
48
+
40
49
  <!-- GET endpoint for redirect statistics -->
41
50
  <plone:service
42
51
  method="GET"
@@ -0,0 +1,89 @@
1
+ """RestAPI endpoint @redirects-import POST (CSV upload)."""
2
+
3
+ import csv
4
+ import io
5
+ import plone.protect.interfaces
6
+ from plone.restapi.services import Service
7
+ from zExceptions import BadRequest
8
+ from zope.component import getUtility
9
+ from zope.interface import alsoProvides
10
+ from zope.interface import implementer
11
+ from zope.publisher.interfaces import IPublishTraverse
12
+
13
+ from eea.api.redirector.interfaces import IStorageUtility
14
+ from eea.api.redirector.restapi.add import add_redirects
15
+
16
+
17
+ @implementer(IPublishTraverse)
18
+ class RedisRedirectsCSVImport(Service):
19
+ """Import redirects from a CSV file upload."""
20
+
21
+ def _get_uploaded_file(self):
22
+ file_upload = self.request.form.get("file")
23
+ if not file_upload:
24
+ raise BadRequest(
25
+ "No file uploaded. Expected multipart/form-data with 'file' field."
26
+ )
27
+ return file_upload
28
+
29
+ def _parse_csv(self, file_upload):
30
+ data = file_upload.read()
31
+ if not data:
32
+ raise BadRequest("CSV file is empty")
33
+
34
+ try:
35
+ text = data.decode("utf-8-sig")
36
+ except Exception as err:
37
+ raise BadRequest(f"Failed to decode CSV file: {err}") from err
38
+
39
+ reader = csv.reader(io.StringIO(text))
40
+ redirects = []
41
+ failed_rows = []
42
+
43
+ for index, row in enumerate(reader):
44
+ if index == 0:
45
+ continue
46
+ if not row or all(not cell.strip() for cell in row):
47
+ continue
48
+
49
+ old_url = row[0].strip() if len(row) > 0 else ""
50
+ new_url = row[1].strip() if len(row) > 1 else ""
51
+
52
+ if not old_url:
53
+ failed_rows.append({"row": index + 1, "error": "Missing old URL"})
54
+ continue
55
+
56
+ redirects.append({"path": old_url, "redirect-to": new_url})
57
+
58
+ return redirects, failed_rows
59
+
60
+ def reply(self):
61
+ """Import redirects to Redis storage from CSV."""
62
+ if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
63
+ alsoProvides(self.request, plone.protect.interfaces.IDisableCSRFProtection)
64
+
65
+ file_upload = self._get_uploaded_file()
66
+ redirects, failed_rows = self._parse_csv(file_upload)
67
+
68
+ if not redirects and not failed_rows:
69
+ raise BadRequest("No valid redirects found in CSV file")
70
+
71
+ storage = getUtility(IStorageUtility)
72
+ success_count, failed_redirects = add_redirects(storage, redirects)
73
+ failed = failed_rows + failed_redirects
74
+
75
+ if failed:
76
+ self.request.response.setStatus(207) # Multi-Status
77
+ return {
78
+ "type": "partial_success" if success_count > 0 else "error",
79
+ "success_count": success_count,
80
+ "failed_count": len(failed),
81
+ "failed": failed,
82
+ }
83
+
84
+ return {
85
+ "type": "success",
86
+ "success_count": success_count,
87
+ "failed_count": 0,
88
+ "failed": [],
89
+ }