slack-objects 0.1.1__tar.gz → 0.1.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 (73) hide show
  1. slack_objects-0.1.2/.github/copilot-instructions.md +8 -0
  2. {slack_objects-0.1.1 → slack_objects-0.1.2}/PKG-INFO +1 -1
  3. slack_objects-0.1.2/src/slack_objects/_version.py +24 -0
  4. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/users.py +12 -4
  5. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects.egg-info/PKG-INFO +1 -1
  6. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/SCIM/test_scim_users_update_attribute_live.py +15 -0
  7. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Smoke/users_smoke_test.py +17 -5
  8. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/UnitTests/users_unit_test.py +90 -0
  9. slack_objects-0.1.1/.github/copilot-instructions.md +0 -5
  10. slack_objects-0.1.1/src/slack_objects/_version.py +0 -34
  11. {slack_objects-0.1.1 → slack_objects-0.1.2}/.github/workflows/ci.yml +0 -0
  12. {slack_objects-0.1.1 → slack_objects-0.1.2}/.github/workflows/publish-pypi.yml +0 -0
  13. {slack_objects-0.1.1 → slack_objects-0.1.2}/.github/workflows/publish-testpypi.yml +0 -0
  14. {slack_objects-0.1.1 → slack_objects-0.1.2}/.gitignore +0 -0
  15. {slack_objects-0.1.1 → slack_objects-0.1.2}/LICENSE +0 -0
  16. {slack_objects-0.1.1 → slack_objects-0.1.2}/README.md +0 -0
  17. {slack_objects-0.1.1 → slack_objects-0.1.2}/pyproject.toml +0 -0
  18. {slack_objects-0.1.1 → slack_objects-0.1.2}/pytest.ini +0 -0
  19. {slack_objects-0.1.1 → slack_objects-0.1.2}/setup.cfg +0 -0
  20. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/__init__.py +0 -0
  21. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/api_caller.py +0 -0
  22. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/base.py +0 -0
  23. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/client.py +0 -0
  24. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/config.py +0 -0
  25. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/conversations.py +0 -0
  26. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/files.py +0 -0
  27. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/idp_groups.py +0 -0
  28. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/messages.py +0 -0
  29. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/rate_limits.py +0 -0
  30. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/scim_base.py +0 -0
  31. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/usergroups.py +0 -0
  32. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects/workspaces.py +0 -0
  33. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects.egg-info/SOURCES.txt +0 -0
  34. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects.egg-info/dependency_links.txt +0 -0
  35. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects.egg-info/requires.txt +0 -0
  36. {slack_objects-0.1.1 → slack_objects-0.1.2}/src/slack_objects.egg-info/top_level.txt +0 -0
  37. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Examples/examples_config.example.json +0 -0
  38. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Examples/users_search_by_email_example.py +0 -0
  39. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Examples/users_test_AzureKeyVault.py +0 -0
  40. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/SCIM/conftest_live.py +0 -0
  41. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/SCIM/run_all_scim_users_live_tests.py +0 -0
  42. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/SCIM/test_scim_idp_groups_live.py +0 -0
  43. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/SCIM/test_scim_users_create_live.py +0 -0
  44. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/SCIM/test_scim_users_deactivate_live.py +0 -0
  45. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/SCIM/test_scim_users_input_validation_live.py +0 -0
  46. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/SCIM/test_scim_users_make_guest_live.py +0 -0
  47. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/SCIM/test_scim_users_reactivate_live.py +0 -0
  48. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/SCIM/test_scim_users_update_email_live.py +0 -0
  49. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Smoke/_smoke_harness.py +0 -0
  50. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Smoke/api_caller_smoke_test.py +0 -0
  51. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Smoke/conversations_smoke_test.py +0 -0
  52. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Smoke/files_smoke_test.py +0 -0
  53. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Smoke/idp_groups_smoke_test.py +0 -0
  54. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Smoke/messages_smoke_test.py +0 -0
  55. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Smoke/run_all_smoke.py +0 -0
  56. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Smoke/security_smoke_test.py +0 -0
  57. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Smoke/usergroups_smoke_test.py +0 -0
  58. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Smoke/workspaces_smoke_test.py +0 -0
  59. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/UnitTests/config_unit_test.py +0 -0
  60. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/UnitTests/conversations_unit_test.py +0 -0
  61. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/UnitTests/files_unit_test.py +0 -0
  62. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/UnitTests/idp_groups_unit_test.py +0 -0
  63. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/UnitTests/messages_unit_test.py +0 -0
  64. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/UnitTests/rate_limits_unit_test.py +0 -0
  65. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/UnitTests/usergroups_test.py +0 -0
  66. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/UnitTests/workspaces_unit_test.py +0 -0
  67. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Users/conftest_live.py +0 -0
  68. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Users/run_all_users_live_tests.py +0 -0
  69. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Users/test_users_admin_live.py +0 -0
  70. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Users/test_users_classification_live.py +0 -0
  71. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Users/test_users_input_validation_live.py +0 -0
  72. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/Users/test_users_read_live.py +0 -0
  73. {slack_objects-0.1.1 → slack_objects-0.1.2}/tests/live_test_config.example.json +0 -0
@@ -0,0 +1,8 @@
1
+ # Copilot Instructions
2
+
3
+ ## Project Guidelines
4
+ - Follow Unix philosophy: build small, composable functions where higher-level methods leverage lower-level primitives. Don't mix concerns (e.g., don't embed identifier resolution inside a SCIM CRUD method). Keep signatures consistent across sibling methods.
5
+ - Prefer consistency with the `Users.is_active`/`is_active_scim` pattern when structuring related methods (separate explicit SCIM method from higher-level orchestration).
6
+
7
+ ## Testing Guidelines
8
+ - Unit test files in `tests/UnitTests` must follow the naming convention `*_unit_test.py` (not `test_*` prefix). The following files should adhere to this convention: `users_unit_test.py`, `conversations_unit_test.py`, `messages_unit_test.py`, `files_unit_test.py`, `workspaces_unit_test.py`, `idp_groups_unit_test.py`, `config_unit_test.py`, and two others with the `_unit_test.py` suffix.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slack-objects
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Opinionated, testable Python wrappers for Slack’s Web, Admin, and SCIM APIs, organized by object domain (users, conversations, messages, files, workspaces, and IdP groups). Designed for automation and administration workflows.
5
5
  Author-email: "Marcos E. Mercado" <marcos_elias@hotmail.com>
6
6
  Keywords: slack,objects,classes,slack objects,utilities,slack utilities,slack object types,slack types,types
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '0.1.2'
22
+ __version_tuple__ = version_tuple = (0, 1, 2)
23
+
24
+ __commit_id__ = commit_id = 'ge0d1b7810'
@@ -626,12 +626,20 @@ class Users(ScimMixin, SlackObjectBase):
626
626
  def scim_update_user_attribute(
627
627
  self,
628
628
  *,
629
- user_id: str,
629
+ user_id: Optional[str] = None,
630
630
  attribute: str,
631
631
  new_value: Any,
632
632
  ) -> ScimResponse:
633
- """SCIM PATCH Users/<id>"""
634
- validate_scim_id(user_id, "user_id")
633
+ """SCIM PATCH Users/<id> for simple scalar attributes.
634
+
635
+ For email updates, use :meth:`scim_update_email` instead — it handles
636
+ the version-specific payload formatting needed to avoid multi-primary
637
+ conflicts.
638
+ """
639
+ uid = user_id or self.user_id
640
+ if not uid:
641
+ raise ValueError("scim_update_user_attribute requires user_id (passed or bound)")
642
+ validate_scim_id(uid, "user_id")
635
643
 
636
644
  scim_version = self.cfg.scim_version
637
645
  if scim_version == "v2":
@@ -644,7 +652,7 @@ class Users(ScimMixin, SlackObjectBase):
644
652
  else:
645
653
  raise NotImplementedError(f"Invalid SCIM version: {scim_version}")
646
654
 
647
- return self._scim_request(path=f"Users/{user_id}", method="PATCH", payload=payload)
655
+ return self._scim_request(path=f"Users/{uid}", method="PATCH", payload=payload)
648
656
 
649
657
  def scim_update_email(
650
658
  self,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slack-objects
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Opinionated, testable Python wrappers for Slack’s Web, Admin, and SCIM APIs, organized by object domain (users, conversations, messages, files, workspaces, and IdP groups). Designed for automation and administration workflows.
5
5
  Author-email: "Marcos E. Mercado" <marcos_elias@hotmail.com>
6
6
  Keywords: slack,objects,classes,slack objects,utilities,slack utilities,slack object types,slack types,types
@@ -190,6 +190,21 @@ class TestScimUpdateUserAttribute:
190
190
  )
191
191
  _pause()
192
192
 
193
+ # ----- bound user_id (no explicit user_id) -----
194
+
195
+ def test_update_attribute_bound_user(self, ctx, users):
196
+ """Update attribute using bound user_id (no explicit user_id arg)."""
197
+ bound = users.with_user(ctx.active_member_id)
198
+ resp = bound.scim_update_user_attribute(
199
+ attribute="title",
200
+ new_value="Bound Test Title",
201
+ )
202
+ assert resp.ok, f"Expected ok for bound user: {resp.data}"
203
+ _pause()
204
+
205
+ bound.scim_update_user_attribute(attribute="title", new_value="")
206
+ _pause()
207
+
193
208
  # ----- deactivated user -----
194
209
 
195
210
  def test_update_attribute_deactivated_user(self, ctx, users):
@@ -110,17 +110,18 @@ def main() -> None:
110
110
  CallSpec("get_user_id_from_email(miss)", lambda: users.get_user_id_from_email("missing@example.com")),
111
111
 
112
112
  # Profile helpers
113
- CallSpec("get_user_profile(bound)", lambda: bound.get_user_profile()),
113
+ CallSpec("get_user_profile()", lambda: bound.get_user_profile()),
114
114
  CallSpec("get_user_profile(by id)", lambda: users.get_user_profile("U1")),
115
- CallSpec("set_user_profile_field(bound)", lambda: bound.set_user_profile_field("status_text", "hello")),
115
+ CallSpec("set_user_profile_field()", lambda: bound.set_user_profile_field("status_text", "hello")),
116
116
  CallSpec("set_user_profile_field(by id)", lambda: users.set_user_profile_field("status_text", "hello", user_id="U1")),
117
117
 
118
118
  # Classification helpers (need attributes)
119
119
  CallSpec("is_contingent_worker()", lambda: (_refresh_bound(), bound.is_contingent_worker())),
120
120
  CallSpec("is_guest()", lambda: (_refresh_bound(), bound.is_guest())),
121
121
  CallSpec("is_active()", lambda: (_refresh_bound(), bound.is_active())),
122
- CallSpec("is_active(user_id override)", lambda: (_refresh_bound(), bound.is_active(user_id="U2"))),
122
+ CallSpec("is_active(by id)", lambda: (_refresh_bound(), bound.is_active(user_id="U2"))),
123
123
  CallSpec("is_active_scim()", lambda: bound.is_active_scim()),
124
+ CallSpec("is_active_scim(by id)", lambda: bound.is_active_scim(user_id="U1")),
124
125
 
125
126
  # Admin helpers
126
127
  CallSpec(
@@ -128,6 +129,7 @@ def main() -> None:
128
129
  lambda: bound.invite_user(channel_ids=["C1", "C2"], email="new@example.com", team_id="T1"),
129
130
  ),
130
131
  CallSpec("wipe_all_sessions()", lambda: bound.wipe_all_sessions()),
132
+ CallSpec("wipe_all_sessions(by id)", lambda: bound.wipe_all_sessions(user_id="U1")),
131
133
  CallSpec("add_to_workspace()", lambda: bound.add_to_workspace("U1", "T1")),
132
134
  CallSpec("remove_from_workspace()", lambda: bound.remove_from_workspace("U1", "T1")),
133
135
  CallSpec("add_to_conversation()", lambda: bound.add_to_conversation(["U1"], "C1")),
@@ -152,24 +154,34 @@ def main() -> None:
152
154
  "set_guest_expiration_date()",
153
155
  lambda: bound.set_guest_expiration_date("2030-01-01", workspace_id="T1"),
154
156
  ),
157
+ CallSpec(
158
+ "set_guest_expiration_date(by id)",
159
+ lambda: bound.set_guest_expiration_date("2030-01-01", user_id="U1", workspace_id="T1"),
160
+ ),
155
161
 
156
162
  # SCIM helpers (scim_version now comes from cfg, not a kwarg)
157
163
  CallSpec("scim_create_user()", lambda: bound.scim_create_user("testuser", "test@example.com")),
158
164
  CallSpec("scim_deactivate_user()", lambda: bound.scim_deactivate_user("U1")),
159
165
  CallSpec("scim_reactivate_user()", lambda: bound.scim_reactivate_user()),
166
+ CallSpec("scim_reactivate_user(by id)", lambda: bound.scim_reactivate_user(user_id="U1")),
160
167
  CallSpec(
161
- "scim_update_user_attribute()",
168
+ "scim_update_user_attribute(by id)",
162
169
  lambda: bound.scim_update_user_attribute(user_id="U1", attribute="active", new_value=False),
163
170
  ),
171
+ CallSpec(
172
+ "scim_update_user_attribute()",
173
+ lambda: bound.scim_update_user_attribute(attribute="active", new_value=False),
174
+ ),
164
175
  CallSpec(
165
176
  "scim_update_email(by id)",
166
177
  lambda: bound.scim_update_email(user_id="U1", new_email="newemail@example.com"),
167
178
  ),
168
179
  CallSpec(
169
- "scim_update_email(bound)",
180
+ "scim_update_email()",
170
181
  lambda: bound.scim_update_email(new_email="newemail@example.com"),
171
182
  ),
172
183
  CallSpec("make_multi_channel_guest()", lambda: bound.make_multi_channel_guest()),
184
+ CallSpec("make_multi_channel_guest(by id)", lambda: bound.make_multi_channel_guest(user_id="U1")),
173
185
 
174
186
  # SCIM search primitives
175
187
  CallSpec("scim_search_user_by_email()", lambda: bound.scim_search_user_by_email("test@example.com")),
@@ -573,3 +573,93 @@ class TestScimUpdateEmail:
573
573
  users = _make_users()
574
574
  with pytest.raises(ValueError):
575
575
  users.scim_update_email(user_id="", new_email="x@example.com")
576
+
577
+
578
+ # ═══════════════════════════════════════════════════════════════════════════
579
+ # scim_update_user_attribute
580
+ # ═══════════════════════════════════════════════════════════════════════════
581
+
582
+ class TestScimUpdateUserAttribute:
583
+ """scim_update_user_attribute — version-aware SCIM PATCH for scalar attributes."""
584
+
585
+ def test_v2_payload_structure(self):
586
+ """v2 uses PatchOp schema with replace operation."""
587
+ users = _make_users()
588
+ bound = users.with_user("U1")
589
+ bound._scim_request = MagicMock(
590
+ return_value=ScimResponse(ok=True, status_code=200, data={}, text=""),
591
+ )
592
+ bound.scim_update_user_attribute(user_id="U1", attribute="active", new_value=False)
593
+
594
+ bound._scim_request.assert_called_once()
595
+ _, kwargs = bound._scim_request.call_args
596
+ op = kwargs["payload"]["Operations"][0]
597
+ assert op["op"] == "replace"
598
+ assert op["path"] == "active"
599
+ assert op["value"] is False
600
+
601
+ def test_v1_payload_structure(self):
602
+ """v1 sets attribute directly on payload root."""
603
+ users = _make_users()
604
+ bound = users.with_user("U1")
605
+ object.__setattr__(bound.cfg, "scim_version", "v1")
606
+ bound._scim_request = MagicMock(
607
+ return_value=ScimResponse(ok=True, status_code=200, data={}, text=""),
608
+ )
609
+ bound.scim_update_user_attribute(user_id="U1", attribute="active", new_value=False)
610
+
611
+ bound._scim_request.assert_called_once()
612
+ _, kwargs = bound._scim_request.call_args
613
+ assert kwargs["payload"]["active"] is False
614
+
615
+ def test_falls_back_to_bound_user_id(self):
616
+ """Omitting user_id uses self.user_id."""
617
+ users = _make_users()
618
+ bound = users.with_user("U1")
619
+ bound._scim_request = MagicMock(
620
+ return_value=ScimResponse(ok=True, status_code=200, data={}, text=""),
621
+ )
622
+ bound.scim_update_user_attribute(attribute="displayName", new_value="Alice")
623
+
624
+ bound._scim_request.assert_called_once()
625
+ _, kwargs = bound._scim_request.call_args
626
+ assert kwargs["path"] == "Users/U1"
627
+
628
+ def test_explicit_user_id_overrides_bound(self):
629
+ """Passing user_id explicitly takes precedence over bound user_id."""
630
+ users = _make_users()
631
+ bound = users.with_user("U_IGNORED")
632
+ bound._scim_request = MagicMock(
633
+ return_value=ScimResponse(ok=True, status_code=200, data={}, text=""),
634
+ )
635
+ bound.scim_update_user_attribute(user_id="U_OTHER", attribute="active", new_value=True)
636
+
637
+ bound._scim_request.assert_called_once()
638
+ _, kwargs = bound._scim_request.call_args
639
+ assert kwargs["path"] == "Users/U_OTHER"
640
+
641
+ def test_no_user_id_raises(self):
642
+ """Unbound instance with no user_id raises ValueError."""
643
+ users = _make_users()
644
+ with pytest.raises(ValueError, match="requires user_id"):
645
+ users.scim_update_user_attribute(attribute="active", new_value=False)
646
+
647
+ def test_invalid_scim_version_raises(self):
648
+ """Unsupported scim_version raises NotImplementedError."""
649
+ users = _make_users()
650
+ bound = users.with_user("U1")
651
+ object.__setattr__(bound.cfg, "scim_version", "v99")
652
+ with pytest.raises(NotImplementedError, match="Invalid SCIM version"):
653
+ bound.scim_update_user_attribute(attribute="active", new_value=False)
654
+
655
+ def test_invalid_user_id_raises(self):
656
+ """Path-traversal user_id is rejected by validate_scim_id."""
657
+ users = _make_users()
658
+ with pytest.raises(ValueError):
659
+ users.scim_update_user_attribute(user_id="../../bad", attribute="active", new_value=False)
660
+
661
+ def test_empty_user_id_raises(self):
662
+ """Empty user_id is rejected by validate_scim_id."""
663
+ users = _make_users()
664
+ with pytest.raises(ValueError):
665
+ users.scim_update_user_attribute(user_id="", attribute="active", new_value=False)
@@ -1,5 +0,0 @@
1
- # Copilot Instructions
2
-
3
- ## Project Guidelines
4
- - Follow Unix philosophy: build small, composable functions where higher-level methods leverage lower-level primitives. Don't mix concerns (e.g., don't embed identifier resolution inside a SCIM CRUD method). Keep signatures consistent across sibling methods.
5
- - Prefer consistency with the `Users.is_active`/`is_active_scim` pattern when structuring related methods (separate explicit SCIM method from higher-level orchestration).
@@ -1,34 +0,0 @@
1
- # file generated by setuptools-scm
2
- # don't change, don't track in version control
3
-
4
- __all__ = [
5
- "__version__",
6
- "__version_tuple__",
7
- "version",
8
- "version_tuple",
9
- "__commit_id__",
10
- "commit_id",
11
- ]
12
-
13
- TYPE_CHECKING = False
14
- if TYPE_CHECKING:
15
- from typing import Tuple
16
- from typing import Union
17
-
18
- VERSION_TUPLE = Tuple[Union[int, str], ...]
19
- COMMIT_ID = Union[str, None]
20
- else:
21
- VERSION_TUPLE = object
22
- COMMIT_ID = object
23
-
24
- version: str
25
- __version__: str
26
- __version_tuple__: VERSION_TUPLE
27
- version_tuple: VERSION_TUPLE
28
- commit_id: COMMIT_ID
29
- __commit_id__: COMMIT_ID
30
-
31
- __version__ = version = '0.1.1'
32
- __version_tuple__ = version_tuple = (0, 1, 1)
33
-
34
- __commit_id__ = commit_id = 'g74ff4e47f'
File without changes
File without changes
File without changes
File without changes
File without changes