data-sourcerer 0.2.0__tar.gz → 0.2.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 (149) hide show
  1. data_sourcerer-0.2.2/.gitignore +190 -0
  2. {data_sourcerer-0.2.0 → data_sourcerer-0.2.2}/PKG-INFO +23 -21
  3. {data_sourcerer-0.2.0 → data_sourcerer-0.2.2}/README.md +2 -2
  4. {data_sourcerer-0.2.0 → data_sourcerer-0.2.2}/pyproject.toml +18 -3
  5. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/__init__.py +1 -1
  6. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/access_credentials/entities.py +4 -7
  7. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/access_credentials/repositories.py +12 -0
  8. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/access_credentials/services.py +2 -1
  9. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/file_system/entities.py +5 -7
  10. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/storage_provider/entities.py +7 -11
  11. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/access_credentials/registry.py +1 -1
  12. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/access_credentials/repositories.py +17 -0
  13. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/access_credentials/services.py +30 -14
  14. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/db/config.py +1 -1
  15. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/storage_provider/services/azure.py +5 -3
  16. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/utils.py +115 -1
  17. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/critical_error/main.py +4 -4
  18. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/file_system_finder/main.py +7 -3
  19. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/file_system_finder/widgets/file_system_navigator.py +1 -1
  20. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/main.py +37 -6
  21. data_sourcerer-0.2.2/sourcerer/presentation/screens/main/messages/refresh_storages_list_request.py +8 -0
  22. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/widgets/gradient.py +3 -3
  23. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/widgets/resizing_rule.py +3 -1
  24. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/widgets/storage_content.py +47 -18
  25. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/widgets/storage_list_sidebar.py +38 -6
  26. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/preview_content/main.py +5 -5
  27. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/provider_creds_list/main.py +44 -0
  28. data_sourcerer-0.2.2/sourcerer/presentation/screens/provider_creds_list/messages/reload_credentials_request.py +8 -0
  29. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/provider_creds_list/styles.tcss +5 -5
  30. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/provider_creds_registration/main.py +6 -2
  31. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/question/main.py +4 -3
  32. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/question/styles.tcss +2 -8
  33. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/shared/widgets/button.py +1 -1
  34. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/shared/widgets/labeled_input.py +6 -2
  35. data_sourcerer-0.2.2/sourcerer/presentation/screens/shared/widgets/loader.py +31 -0
  36. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/storage_action_progress/main.py +28 -26
  37. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/utils.py +1 -1
  38. data_sourcerer-0.2.0/.coderabbit.yaml +0 -49
  39. data_sourcerer-0.2.0/.github/workflows/bandit.yml +0 -27
  40. data_sourcerer-0.2.0/.github/workflows/deploy_docs.yml +0 -28
  41. data_sourcerer-0.2.0/.github/workflows/pylint.yml +0 -28
  42. data_sourcerer-0.2.0/.github/workflows/pyright.yml +0 -26
  43. data_sourcerer-0.2.0/.github/workflows/ruff.yml +0 -25
  44. data_sourcerer-0.2.0/.github/workflows/run_tests.yml +0 -23
  45. data_sourcerer-0.2.0/.gitignore +0 -2
  46. data_sourcerer-0.2.0/.pre-commit-config.yaml +0 -10
  47. data_sourcerer-0.2.0/.pylintrc +0 -644
  48. data_sourcerer-0.2.0/docs/assets/billie-holiday.png +0 -0
  49. data_sourcerer-0.2.0/docs/assets/creds_registration.gif +0 -0
  50. data_sourcerer-0.2.0/docs/assets/keys_operations.gif +0 -0
  51. data_sourcerer-0.2.0/docs/assets/layer-1.png +0 -0
  52. data_sourcerer-0.2.0/docs/assets/layer-2.png +0 -0
  53. data_sourcerer-0.2.0/docs/assets/layer-3.png +0 -0
  54. data_sourcerer-0.2.0/docs/assets/layer-4.png +0 -0
  55. data_sourcerer-0.2.0/docs/assets/layer-5.png +0 -0
  56. data_sourcerer-0.2.0/docs/guides/register_credentials.md +0 -1
  57. data_sourcerer-0.2.0/docs/index.md +0 -4
  58. data_sourcerer-0.2.0/docs/js/parallax.js +0 -33
  59. data_sourcerer-0.2.0/docs/overrides/home.html +0 -312
  60. data_sourcerer-0.2.0/docs/roadmap.md +0 -49
  61. data_sourcerer-0.2.0/docs/styles/styles.css +0 -0
  62. data_sourcerer-0.2.0/media/creds_registration.gif +0 -0
  63. data_sourcerer-0.2.0/media/keys_operations.gif +0 -0
  64. data_sourcerer-0.2.0/mkdocs.yml +0 -63
  65. data_sourcerer-0.2.0/setup.cfg +0 -4
  66. data_sourcerer-0.2.0/src/data_sourcerer.egg-info/PKG-INFO +0 -73
  67. data_sourcerer-0.2.0/src/data_sourcerer.egg-info/SOURCES.txt +0 -143
  68. data_sourcerer-0.2.0/src/data_sourcerer.egg-info/dependency_links.txt +0 -1
  69. data_sourcerer-0.2.0/src/data_sourcerer.egg-info/entry_points.txt +0 -2
  70. data_sourcerer-0.2.0/src/data_sourcerer.egg-info/requires.txt +0 -25
  71. data_sourcerer-0.2.0/src/data_sourcerer.egg-info/top_level.txt +0 -1
  72. data_sourcerer-0.2.0/tests/README.md +0 -57
  73. data_sourcerer-0.2.0/tests/sourcerer/__init__.py +0 -0
  74. data_sourcerer-0.2.0/tests/sourcerer/access_credentials/__init__.py +0 -0
  75. data_sourcerer-0.2.0/tests/sourcerer/access_credentials/test_registry.py +0 -119
  76. data_sourcerer-0.2.0/tests/sourcerer/access_credentials/test_repositories.py +0 -131
  77. data_sourcerer-0.2.0/tests/sourcerer/access_credentials/test_services.py +0 -461
  78. data_sourcerer-0.2.0/tests/sourcerer/db/__init__.py +0 -0
  79. data_sourcerer-0.2.0/tests/sourcerer/db/test_models.py +0 -66
  80. data_sourcerer-0.2.0/tests/sourcerer/file_system/__init__.py +0 -0
  81. data_sourcerer-0.2.0/tests/sourcerer/file_system/test_services.py +0 -99
  82. data_sourcerer-0.2.0/tests/sourcerer/storage_provider/__init__.py +0 -0
  83. data_sourcerer-0.2.0/tests/sourcerer/storage_provider/test_registry.py +0 -82
  84. data_sourcerer-0.2.0/tests/sourcerer/storage_provider/test_services.py +0 -919
  85. data_sourcerer-0.2.0/uv.lock +0 -2885
  86. {data_sourcerer-0.2.0 → data_sourcerer-0.2.2}/LICENSE +0 -0
  87. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/__init__.py +0 -0
  88. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/access_credentials/__init__.py +0 -0
  89. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/access_credentials/exceptions.py +0 -0
  90. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/file_system/__init__.py +0 -0
  91. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/file_system/exceptions.py +0 -0
  92. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/file_system/services.py +0 -0
  93. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/shared/__init__.py +0 -0
  94. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/shared/entities.py +0 -0
  95. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/storage_provider/__init__.py +0 -0
  96. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/storage_provider/exceptions.py +0 -0
  97. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/domain/storage_provider/services.py +0 -0
  98. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/__init__.py +0 -0
  99. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/access_credentials/__init__.py +0 -0
  100. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/access_credentials/exceptions.py +0 -0
  101. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/db/__init__.py +0 -0
  102. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/db/models.py +0 -0
  103. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/file_system/__init__.py +0 -0
  104. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/file_system/exceptions.py +0 -0
  105. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/file_system/services.py +0 -0
  106. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/storage_provider/__init__.py +0 -0
  107. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/storage_provider/exceptions.py +0 -0
  108. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/storage_provider/registry.py +0 -0
  109. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/storage_provider/services/__init__.py +0 -0
  110. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/storage_provider/services/gcp.py +0 -0
  111. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/infrastructure/storage_provider/services/s3.py +0 -0
  112. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/__init__.py +0 -0
  113. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/app.py +0 -0
  114. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/di_container.py +0 -0
  115. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/__init__.py +0 -0
  116. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/critical_error/__init__.py +0 -0
  117. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/critical_error/styles.tcss +0 -0
  118. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/file_system_finder/styles.tcss +0 -0
  119. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/file_system_finder/widgets/__init__.py +0 -0
  120. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/__init__.py +0 -0
  121. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/messages/__init__.py +0 -0
  122. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/messages/delete_request.py +0 -0
  123. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/messages/download_request.py +0 -0
  124. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/messages/preview_request.py +0 -0
  125. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/messages/resizing_rule.py +0 -0
  126. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/messages/select_storage_item.py +0 -0
  127. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/messages/uncheck_files_request.py +0 -0
  128. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/messages/upload_request.py +0 -0
  129. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/mixins/__init__.py +0 -0
  130. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/mixins/resize_containers_watcher_mixin.py +0 -0
  131. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/styles.tcss +0 -0
  132. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/main/widgets/__init__.py +0 -0
  133. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/preview_content/__init__.py +0 -0
  134. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/preview_content/styles.tcss +0 -0
  135. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/provider_creds_list/__init__.py +0 -0
  136. {data_sourcerer-0.2.0/src/sourcerer/presentation/screens/provider_creds_registration → data_sourcerer-0.2.2/sourcerer/presentation/screens/provider_creds_list/messages}/__init__.py +0 -0
  137. {data_sourcerer-0.2.0/src/sourcerer/presentation/screens/question → data_sourcerer-0.2.2/sourcerer/presentation/screens/provider_creds_registration}/__init__.py +0 -0
  138. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/provider_creds_registration/styles.tcss +0 -0
  139. {data_sourcerer-0.2.0/src/sourcerer/presentation/screens/shared → data_sourcerer-0.2.2/sourcerer/presentation/screens/question}/__init__.py +0 -0
  140. {data_sourcerer-0.2.0/src/sourcerer/presentation/screens/shared/widgets → data_sourcerer-0.2.2/sourcerer/presentation/screens/shared}/__init__.py +0 -0
  141. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/shared/containers.py +0 -0
  142. {data_sourcerer-0.2.0/src/sourcerer/presentation/screens/storage_action_progress → data_sourcerer-0.2.2/sourcerer/presentation/screens/shared/widgets}/__init__.py +0 -0
  143. {data_sourcerer-0.2.0/src/sourcerer/presentation/themes → data_sourcerer-0.2.2/sourcerer/presentation/screens/storage_action_progress}/__init__.py +0 -0
  144. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/screens/storage_action_progress/styles.tcss +0 -0
  145. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/settings.py +0 -0
  146. {data_sourcerer-0.2.0/tests → data_sourcerer-0.2.2/sourcerer/presentation/themes}/__init__.py +0 -0
  147. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/themes/github_dark.py +0 -0
  148. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/presentation/utils.py +0 -0
  149. {data_sourcerer-0.2.0/src → data_sourcerer-0.2.2}/sourcerer/settings.py +0 -0
@@ -0,0 +1,190 @@
1
+
2
+ .qodo
3
+ # Byte-compiled / optimized / DLL files
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+
8
+ # C extensions
9
+ *.so
10
+
11
+ # Distribution / packaging
12
+ .Python
13
+ build/
14
+ develop-eggs/
15
+ dist/
16
+ downloads/
17
+ eggs/
18
+ .eggs/
19
+ lib/
20
+ lib64/
21
+ parts/
22
+ sdist/
23
+ var/
24
+ wheels/
25
+ share/python-wheels/
26
+ *.egg-info/
27
+ .installed.cfg
28
+ *.egg
29
+ MANIFEST
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
+ cover/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ .pybuilder/
78
+ target/
79
+
80
+ # Jupyter Notebook
81
+ .ipynb_checkpoints
82
+
83
+ # IPython
84
+ profile_default/
85
+ ipython_config.py
86
+
87
+ # pyenv
88
+ # For a library or package, you might want to ignore these files since the code is
89
+ # intended to run in multiple environments; otherwise, check them in:
90
+ # .python-version
91
+
92
+ # pipenv
93
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
95
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
96
+ # install all needed dependencies.
97
+ #Pipfile.lock
98
+
99
+ # UV
100
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
101
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
102
+ # commonly ignored for libraries.
103
+ #uv.lock
104
+
105
+ # poetry
106
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
107
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
108
+ # commonly ignored for libraries.
109
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
110
+ #poetry.lock
111
+
112
+ # pdm
113
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
114
+ #pdm.lock
115
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
116
+ # in version control.
117
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
118
+ .pdm.toml
119
+ .pdm-python
120
+ .pdm-build/
121
+
122
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
123
+ __pypackages__/
124
+
125
+ # Celery stuff
126
+ celerybeat-schedule
127
+ celerybeat.pid
128
+
129
+ # SageMath parsed files
130
+ *.sage.py
131
+
132
+ # Environments
133
+ .env
134
+ .venv
135
+ env/
136
+ venv/
137
+ ENV/
138
+ env.bak/
139
+ venv.bak/
140
+
141
+ # Spyder project settings
142
+ .spyderproject
143
+ .spyproject
144
+
145
+ # Rope project settings
146
+ .ropeproject
147
+
148
+ # mkdocs documentation
149
+ /site
150
+
151
+ # mypy
152
+ .mypy_cache/
153
+ .dmypy.json
154
+ dmypy.json
155
+
156
+ # Pyre type checker
157
+ .pyre/
158
+
159
+ # pytype static type analyzer
160
+ .pytype/
161
+
162
+ # Cython debug symbols
163
+ cython_debug/
164
+
165
+ # PyCharm
166
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
167
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
168
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
169
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
170
+ #.idea/
171
+
172
+ # Visual Studio Code
173
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
174
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
175
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
176
+ # you could uncomment the following to ignore the enitre vscode folder
177
+ # .vscode/
178
+
179
+ # Ruff stuff:
180
+ .ruff_cache/
181
+
182
+ # PyPI configuration file
183
+ .pypirc
184
+
185
+ # Cursor
186
+ # Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
187
+ # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
188
+ # refer to https://docs.cursor.com/context/ignore-files
189
+ .cursorignore
190
+ .cursorindexingignore
@@ -1,42 +1,44 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: data-sourcerer
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Sourcerer is a terminal cloud storage navigator.
5
5
  Author-email: Bohdana Kuzmenko <bohdana.kuzmenko.dev@gmail.com>
6
6
  License: MIT
7
- Keywords: cloud,s3,gcp,cli,terminal,storage,textual,ui
8
- Requires-Python: >=3.9
9
- Description-Content-Type: text/markdown
10
7
  License-File: LICENSE
8
+ Keywords: cli,cloud,gcp,s3,storage,terminal,textual,ui
9
+ Requires-Python: >=3.9
10
+ Requires-Dist: azure-identity<2.0.0,>=1.22.0
11
+ Requires-Dist: azure-mgmt-storage<23.0.0,>=22.2.0
12
+ Requires-Dist: azure-storage-blob<13.0.0,>=12.25.1
11
13
  Requires-Dist: boto3<2.0.0,>=1.26.0
12
14
  Requires-Dist: cryptography<45.0.0,>=44.0.2
13
15
  Requires-Dist: dependency-injector<5.0.0,>=4.43.0
14
16
  Requires-Dist: google-cloud-storage<4.0.0,>=3.1.0
15
17
  Requires-Dist: humanize<5.0.0,>=4.12.1
16
- Requires-Dist: sqlalchemy<3.0.0,>=2.0.38
18
+ Requires-Dist: msgspec>=0.19.0
19
+ Requires-Dist: pyopenssl>=22.1.0; sys_platform == 'linux'
17
20
  Requires-Dist: sqlalchemy-utils<1.0.0,>=0.41.2
21
+ Requires-Dist: sqlalchemy<3.0.0,>=2.0.38
18
22
  Requires-Dist: textual[syntax]<4.0.0,>=2.0.0
19
- Requires-Dist: pyOpenSSL>=22.1.0; sys_platform == "linux"
20
- Requires-Dist: azure-storage-blob<13.0.0,>=12.25.1
21
- Requires-Dist: azure-identity<2.0.0,>=1.22.0
22
- Requires-Dist: azure-mgmt-storage<23.0.0,>=22.2.0
23
23
  Provides-Extra: dev
24
- Requires-Dist: bandit>=1.8.3; extra == "dev"
25
- Requires-Dist: black>=25.1.0; extra == "dev"
26
- Requires-Dist: coverage>=7.8.0; extra == "dev"
27
- Requires-Dist: mkdocs-material>=9.6.12; extra == "dev"
28
- Requires-Dist: pre-commit>=4.2.0; extra == "dev"
29
- Requires-Dist: pylint>=3.3.6; extra == "dev"
30
- Requires-Dist: pyright>=1.1.400; extra == "dev"
31
- Requires-Dist: ruff>=0.11.7; extra == "dev"
32
- Requires-Dist: textual-dev>=1.7.0; extra == "dev"
33
- Dynamic: license-file
24
+ Requires-Dist: bandit>=1.8.3; extra == 'dev'
25
+ Requires-Dist: black>=25.1.0; extra == 'dev'
26
+ Requires-Dist: coverage>=7.8.0; extra == 'dev'
27
+ Requires-Dist: hatch>=1.14.1; extra == 'dev'
28
+ Requires-Dist: mkdocs-material>=9.6.12; extra == 'dev'
29
+ Requires-Dist: pre-commit>=4.2.0; extra == 'dev'
30
+ Requires-Dist: pylint>=3.3.6; extra == 'dev'
31
+ Requires-Dist: pyright>=1.1.400; extra == 'dev'
32
+ Requires-Dist: ruff>=0.11.7; extra == 'dev'
33
+ Requires-Dist: textual-dev>=1.7.0; extra == 'dev'
34
+ Requires-Dist: ty>=0.0.1a6; extra == 'dev'
35
+ Description-Content-Type: text/markdown
34
36
 
35
37
  # 🧙‍♂️ Sourcerer
36
38
 
37
39
  **Sourcerer** is a CLI-based cloud storage explorer that provides a unified interface for developers and DevOps
38
40
  engineers to view and manage files across multiple cloud providers like
39
- **GCP**, **AWS S3**, and **S3-compatible services**.
41
+ **GCP Storage**, **Azure Storage**, **AWS S3**, and **S3-compatible services**.
40
42
 
41
43
  > Your terminal. Your storages. Your control.
42
44
 
@@ -44,7 +46,7 @@ engineers to view and manage files across multiple cloud providers like
44
46
 
45
47
  ## ✨ Features
46
48
 
47
- - 🔍 Unified file browser for GCP, AWS S3, and S3-compatible services
49
+ - 🔍 Unified file browser for GCP Storage, Azure Storage, AWS S3, and S3-compatible services
48
50
  - 🧭 Terminal UI (TUI) built with [Textual](https://github.com/Textualize/textual)
49
51
  - 🗂️ Explore buckets and objects seamlessly
50
52
  - 🔄 Upload, download, and delete files
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Sourcerer** is a CLI-based cloud storage explorer that provides a unified interface for developers and DevOps
4
4
  engineers to view and manage files across multiple cloud providers like
5
- **GCP**, **AWS S3**, and **S3-compatible services**.
5
+ **GCP Storage**, **Azure Storage**, **AWS S3**, and **S3-compatible services**.
6
6
 
7
7
  > Your terminal. Your storages. Your control.
8
8
 
@@ -10,7 +10,7 @@ engineers to view and manage files across multiple cloud providers like
10
10
 
11
11
  ## ✨ Features
12
12
 
13
- - 🔍 Unified file browser for GCP, AWS S3, and S3-compatible services
13
+ - 🔍 Unified file browser for GCP Storage, Azure Storage, AWS S3, and S3-compatible services
14
14
  - 🧭 Terminal UI (TUI) built with [Textual](https://github.com/Textualize/textual)
15
15
  - 🗂️ Explore buckets and objects seamlessly
16
16
  - 🔄 Upload, download, and delete files
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
 
3
3
  name = "data-sourcerer"
4
- version = "0.2.0"
4
+ version = "0.2.2"
5
5
  description = "Sourcerer is a terminal cloud storage navigator."
6
6
  requires-python = ">=3.9"
7
7
 
@@ -27,26 +27,30 @@ dependencies = [
27
27
  "azure-storage-blob>=12.25.1,<13.0.0",
28
28
  "azure-identity>=1.22.0,<2.0.0",
29
29
  "azure-mgmt-storage>=22.2.0,<23.0.0",
30
+ "msgspec>=0.19.0",
30
31
  ]
31
32
 
32
33
  [project.scripts]
33
34
  sourcerer = "sourcerer.presentation.app:main"
34
35
 
35
36
  [build-system]
36
- requires = ["setuptools >= 61.0", "setuptools-scm"]
37
- build-backend = "setuptools.build_meta"
37
+ requires = ["hatchling"]
38
+ build-backend = "hatchling.build"
38
39
 
39
40
  [dependency-groups]
40
41
  dev = [
41
42
  "bandit>=1.8.3",
42
43
  "black>=25.1.0",
43
44
  "coverage>=7.8.0",
45
+ "hatch>=1.14.1",
44
46
  "mkdocs-material>=9.6.12",
45
47
  "pre-commit>=4.2.0",
46
48
  "pylint>=3.3.6",
47
49
  "pyright>=1.1.400",
48
50
  "ruff>=0.11.7",
49
51
  "textual-dev>=1.7.0",
52
+ "ty>=0.0.1a6",
53
+ "black>=25.1.0",
50
54
  ]
51
55
 
52
56
  [project.optional-dependencies]
@@ -54,12 +58,15 @@ dev = [
54
58
  "bandit>=1.8.3",
55
59
  "black>=25.1.0",
56
60
  "coverage>=7.8.0",
61
+ "hatch>=1.14.1",
57
62
  "mkdocs-material>=9.6.12",
58
63
  "pre-commit>=4.2.0",
59
64
  "pylint>=3.3.6",
60
65
  "pyright>=1.1.400",
61
66
  "ruff>=0.11.7",
62
67
  "textual-dev>=1.7.0",
68
+ "ty>=0.0.1a6",
69
+ "black>=25.1.0",
63
70
  ]
64
71
 
65
72
  [tool.coverage.run]
@@ -96,3 +103,11 @@ unfixable = ["F401"] # unused imports - maybe you want to catch it manually
96
103
 
97
104
  [tool.ruff.mccabe]
98
105
  max-complexity = 10
106
+
107
+ [tool.hatch.build]
108
+ include = ["src"]
109
+ sources = ["src"]
110
+
111
+ [tool.ty.rules]
112
+ unresolved-import = "ignore"
113
+ invalid-assignment = "warn"
@@ -12,4 +12,4 @@ The application is structured using a clean architecture approach with:
12
12
  - Presentation layer: User interface components
13
13
  """
14
14
 
15
- __version__ = "0.2.0"
15
+ __version__ = "0.2.2"
@@ -5,15 +5,14 @@ This module defines data classes representing access credentials
5
5
  used for authentication with various cloud providers.
6
6
  """
7
7
 
8
- from dataclasses import dataclass
9
8
  from datetime import datetime
10
9
 
11
10
  import boto3
12
11
  from azure.identity import ClientSecretCredential
12
+ from msgspec._core import Struct
13
13
 
14
14
 
15
- @dataclass
16
- class Credentials:
15
+ class Credentials(Struct):
17
16
  """
18
17
  Represents access credentials for a provider.
19
18
 
@@ -38,8 +37,7 @@ class Credentials:
38
37
  updated_at: datetime | None = None
39
38
 
40
39
 
41
- @dataclass
42
- class Boto3Credentials:
40
+ class Boto3Credentials(Struct):
43
41
  """
44
42
  Represents AWS credentials using boto3 session.
45
43
 
@@ -54,8 +52,7 @@ class Boto3Credentials:
54
52
  signature_version: str | None = None
55
53
 
56
54
 
57
- @dataclass
58
- class AzureCredentials:
55
+ class AzureCredentials(Struct):
59
56
  """
60
57
  Represents Azure credentials.
61
58
 
@@ -28,6 +28,18 @@ class BaseCredentialsRepository(metaclass=ABCMeta):
28
28
  """
29
29
  raise NotImplementedError
30
30
 
31
+ @abstractmethod
32
+ def delete(self, uuid):
33
+ """Delete credentials by UUID.
34
+
35
+ Args:
36
+ uuid: Unique identifier for the credentials to delete
37
+
38
+ Raises:
39
+ NotImplementedError: Method must be implemented by concrete classes
40
+ """
41
+ raise NotImplementedError
42
+
31
43
  @abstractmethod
32
44
  def get(self, uuid):
33
45
  """Retrieve credentials by UUID.
@@ -8,6 +8,7 @@ authentication methods.
8
8
 
9
9
  from abc import abstractmethod
10
10
  from dataclasses import dataclass
11
+ from typing import Any
11
12
 
12
13
  from sourcerer.domain.access_credentials.repositories import BaseCredentialsRepository
13
14
 
@@ -71,7 +72,7 @@ class BaseAccessCredentialsService:
71
72
  """
72
73
 
73
74
  @abstractmethod
74
- def authenticate(self, credentials: str):
75
+ def authenticate(self, credentials: str) -> Any:
75
76
  """
76
77
  Authenticate using stored credentials.
77
78
 
@@ -5,12 +5,12 @@ This module defines data classes representing file system entities and
5
5
  operation results used throughout the application.
6
6
  """
7
7
 
8
- from dataclasses import dataclass
9
8
  from pathlib import Path
10
9
 
10
+ from msgspec._core import Struct
11
11
 
12
- @dataclass
13
- class SearchResult:
12
+
13
+ class SearchResult(Struct):
14
14
  """
15
15
  Represents the result of a search operation.
16
16
 
@@ -30,8 +30,7 @@ class SearchResult:
30
30
  line: int
31
31
 
32
32
 
33
- @dataclass
34
- class SearchResultOutput:
33
+ class SearchResultOutput(Struct):
35
34
  """
36
35
  Represents the output of a search operation.
37
36
 
@@ -51,8 +50,7 @@ class SearchResultOutput:
51
50
  total: int
52
51
 
53
52
 
54
- @dataclass
55
- class ListDirOutput:
53
+ class ListDirOutput(Struct):
56
54
  """
57
55
  Represents the output of a list directory operation.
58
56
 
@@ -5,12 +5,12 @@ This module defines data classes representing cloud storage entities
5
5
  such as storage containers, files, folders, and permissions.
6
6
  """
7
7
 
8
- from dataclasses import dataclass
9
8
  from datetime import datetime
10
9
 
10
+ from msgspec._core import Struct
11
11
 
12
- @dataclass
13
- class Storage:
12
+
13
+ class Storage(Struct):
14
14
  """
15
15
  Represents a cloud storage container (bucket/container).
16
16
 
@@ -25,8 +25,7 @@ class Storage:
25
25
  date_created: datetime
26
26
 
27
27
 
28
- @dataclass
29
- class StoragePermissions:
28
+ class StoragePermissions(Struct):
30
29
  """
31
30
  Represents permissions for a user on a storage resource.
32
31
 
@@ -39,8 +38,7 @@ class StoragePermissions:
39
38
  permissions: list[str]
40
39
 
41
40
 
42
- @dataclass
43
- class Folder:
41
+ class Folder(Struct):
44
42
  """
45
43
  Represents a folder/directory within a storage container.
46
44
 
@@ -51,8 +49,7 @@ class Folder:
51
49
  key: str
52
50
 
53
51
 
54
- @dataclass
55
- class File:
52
+ class File(Struct):
56
53
  """
57
54
  Represents a file within a storage container.
58
55
 
@@ -71,8 +68,7 @@ class File:
71
68
  date_modified: datetime | None = None
72
69
 
73
70
 
74
- @dataclass
75
- class StorageContent:
71
+ class StorageContent(Struct):
76
72
  """
77
73
  Represents the contents of a storage location, including files and folders.
78
74
 
@@ -37,7 +37,7 @@ class AccessCredentialsRegistry(metaclass=Singleton):
37
37
  def __init__(self, *args, **kwargs):
38
38
  """Initialize the registry with an empty dictionary."""
39
39
  super().__init__(*args, **kwargs)
40
- self._items_: dict[str, dict[str, type]] = {} # type: ignore
40
+ self._items_: dict[str, dict[str, type]] = {}
41
41
 
42
42
  def register(
43
43
  self,
@@ -46,6 +46,23 @@ class SQLAlchemyCredentialsRepository(BaseCredentialsRepository):
46
46
  session.add(credentials)
47
47
  session.commit()
48
48
 
49
+ def delete(self, uuid: str):
50
+ """
51
+ Delete credentials from the database by UUID.
52
+
53
+ Args:
54
+ uuid (str): Unique identifier for the credentials to delete
55
+ """
56
+ with self.db() as session:
57
+ credentials = (
58
+ session.query(DBCredentials).filter(DBCredentials.uuid == uuid).first()
59
+ )
60
+ if credentials is None:
61
+ # No matching credentials found; return early
62
+ return
63
+ session.delete(credentials)
64
+ session.commit()
65
+
49
66
  def get(self, uuid: str):
50
67
  """
51
68
  Retrieve credentials by UUID.
@@ -71,6 +71,15 @@ class CredentialsService:
71
71
  """
72
72
  return self.credentials_repo.list(active_only)
73
73
 
74
+ def delete(self, uuid):
75
+ """
76
+ Delete credentials by UUID.
77
+
78
+ Args:
79
+ uuid (str): Unique identifier for the credentials to delete
80
+ """
81
+ return self.credentials_repo.delete(uuid)
82
+
74
83
  def get(self, uuid):
75
84
  """
76
85
  Get credentials by UUID.
@@ -190,7 +199,7 @@ class S3AccessKeySecretKeyPair(S3AccessCredentialsService):
190
199
  """
191
200
  return self.credentials_repo.get(uuid)
192
201
 
193
- def authenticate(self, credentials: str): # type: ignore
202
+ def authenticate(self, credentials: str):
194
203
  """
195
204
  Authenticate using stored credentials.
196
205
 
@@ -201,22 +210,27 @@ class S3AccessKeySecretKeyPair(S3AccessCredentialsService):
201
210
  boto3.Session: Authenticated boto3 session
202
211
  """
203
212
  try:
204
- credentials: dict = json.loads(credentials)
213
+ credentials_dict: dict = json.loads(credentials)
214
+
215
+ access_key_id = credentials_dict.get("aws_access_key_id")
216
+ secret_access_key = credentials_dict.get("aws_secret_access_key")
217
+ endpoint_url = credentials_dict.get("endpoint_url")
218
+ signature_version = credentials_dict.get("signature_version")
205
219
 
206
220
  session_args = {
207
- "aws_access_key_id": credentials.get("aws_access_key_id"),
208
- "aws_secret_access_key": credentials.get("aws_secret_access_key"),
221
+ "aws_access_key_id": access_key_id,
222
+ "aws_secret_access_key": secret_access_key,
209
223
  }
210
224
 
211
- if region := credentials.get("region"):
225
+ if region := credentials_dict.get("region"):
212
226
  session_args["region_name"] = region
213
227
 
214
228
  session = boto3.Session(**session_args)
215
229
 
216
230
  return Boto3Credentials(
217
231
  session=session,
218
- endpoint_url=credentials.get("endpoint_url", None),
219
- signature_version=credentials.get("signature_version", None),
232
+ endpoint_url=endpoint_url,
233
+ signature_version=signature_version,
220
234
  )
221
235
  except Exception as e:
222
236
  raise CredentialsAuthError("Failed to authenticate") from e
@@ -277,7 +291,7 @@ class S3ProfileName(S3AccessCredentialsService):
277
291
  """
278
292
  return self.credentials_repo.get(uuid)
279
293
 
280
- def authenticate(self, credentials: str): # type: ignore
294
+ def authenticate(self, credentials: str):
281
295
  """
282
296
  Authenticate using stored profile name.
283
297
 
@@ -288,11 +302,14 @@ class S3ProfileName(S3AccessCredentialsService):
288
302
  boto3.Session: Authenticated boto3 session
289
303
  """
290
304
  try:
291
- credentials: dict = json.loads(credentials)
292
- session = boto3.Session(profile_name=credentials.get("profile_name"))
305
+ credentials_dict: dict = json.loads(credentials)
306
+ profile_name = credentials_dict.get("profile_name")
307
+ endpoint_url = credentials_dict.get("endpoint_url")
308
+
309
+ session = boto3.Session(profile_name=profile_name)
293
310
  return Boto3Credentials(
294
311
  session=session,
295
- endpoint_url=credentials.get("endpoint_url"),
312
+ endpoint_url=endpoint_url,
296
313
  )
297
314
  except Exception as e:
298
315
  raise CredentialsAuthError("Failed to authenticate") from e
@@ -353,7 +370,7 @@ class GCPCredentialsService(AccessCredentialsService):
353
370
  """
354
371
  return self.credentials_repo.get(uuid)
355
372
 
356
- def authenticate(self, credentials: str): # type: ignore
373
+ def authenticate(self, credentials: str):
357
374
  """
358
375
  Authenticate with Google Cloud Platform using service account credentials.
359
376
 
@@ -414,7 +431,6 @@ class GCPCredentialsService(AccessCredentialsService):
414
431
  AccessCredentialsMethod(StorageProvider.AzureStorage, "Client Secret Credentials")
415
432
  )
416
433
  class AzureClientSecretCredentialsService(AccessCredentialsService):
417
-
418
434
  def store(self, name, credentials: dict):
419
435
  """
420
436
  Store Azure client_id and secret_key_pair credentials.
@@ -446,7 +462,7 @@ class AzureClientSecretCredentialsService(AccessCredentialsService):
446
462
  """
447
463
  return self.credentials_repo.get(uuid)
448
464
 
449
- def authenticate(self, credentials: str): # type: ignore
465
+ def authenticate(self, credentials: str):
450
466
  try:
451
467
  # Parse the outer JSON structure
452
468
  parsed_credentials = json.loads(credentials)
@@ -30,7 +30,7 @@ class Database:
30
30
  """
31
31
  self.db_url = db_url
32
32
  self.engine = sqlalchemy.create_engine(db_url)
33
- self.scoped_session = scoped_session(sessionmaker(bind=self.engine)) # type: ignore
33
+ self.scoped_session = scoped_session(sessionmaker(bind=self.engine))
34
34
 
35
35
  def prepare_db(self):
36
36
  """