tap-asana 2.2.0__tar.gz → 2.4.0__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 (51) hide show
  1. tap_asana-2.4.0/PKG-INFO +22 -0
  2. {tap-asana-2.2.0 → tap_asana-2.4.0}/README.md +1 -0
  3. {tap-asana-2.2.0 → tap_asana-2.4.0}/setup.py +9 -10
  4. tap_asana-2.4.0/tap_asana/asana.py +67 -0
  5. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/schemas/portfolios.json +53 -2
  6. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/schemas/projects.json +1 -1
  7. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/schemas/stories.json +6 -0
  8. tap_asana-2.4.0/tap_asana/schemas/subtasks.json +916 -0
  9. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/schemas/teams.json +24 -0
  10. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/streams/__init__.py +1 -0
  11. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/streams/base.py +101 -32
  12. tap_asana-2.4.0/tap_asana/streams/portfolios.py +72 -0
  13. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/streams/projects.py +29 -5
  14. tap_asana-2.4.0/tap_asana/streams/sections.py +47 -0
  15. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/streams/stories.py +29 -19
  16. tap_asana-2.4.0/tap_asana/streams/subtasks.py +97 -0
  17. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/streams/tags.py +19 -5
  18. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/streams/tasks.py +28 -18
  19. tap_asana-2.4.0/tap_asana/streams/teams.py +54 -0
  20. tap_asana-2.4.0/tap_asana/streams/users.py +40 -0
  21. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/streams/workspaces.py +13 -1
  22. tap_asana-2.4.0/tap_asana.egg-info/PKG-INFO +22 -0
  23. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana.egg-info/SOURCES.txt +2 -0
  24. tap_asana-2.4.0/tap_asana.egg-info/requires.txt +9 -0
  25. {tap-asana-2.2.0 → tap_asana-2.4.0}/tests/test_all_fields.py +21 -4
  26. {tap-asana-2.2.0 → tap_asana-2.4.0}/tests/test_automatic_fields.py +2 -1
  27. {tap-asana-2.2.0 → tap_asana-2.4.0}/tests/test_bookmarks.py +12 -1
  28. {tap-asana-2.2.0 → tap_asana-2.4.0}/tests/test_start_date.py +13 -2
  29. tap-asana-2.2.0/PKG-INFO +0 -10
  30. tap-asana-2.2.0/tap_asana/asana.py +0 -57
  31. tap-asana-2.2.0/tap_asana/streams/portfolios.py +0 -53
  32. tap-asana-2.2.0/tap_asana/streams/sections.py +0 -40
  33. tap-asana-2.2.0/tap_asana/streams/teams.py +0 -39
  34. tap-asana-2.2.0/tap_asana/streams/users.py +0 -28
  35. tap-asana-2.2.0/tap_asana.egg-info/PKG-INFO +0 -10
  36. tap-asana-2.2.0/tap_asana.egg-info/requires.txt +0 -10
  37. {tap-asana-2.2.0 → tap_asana-2.4.0}/LICENSE +0 -0
  38. {tap-asana-2.2.0 → tap_asana-2.4.0}/MANIFEST.in +0 -0
  39. {tap-asana-2.2.0 → tap_asana-2.4.0}/setup.cfg +0 -0
  40. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/__init__.py +0 -0
  41. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/context.py +0 -0
  42. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/schemas/sections.json +0 -0
  43. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/schemas/tags.json +0 -0
  44. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/schemas/tasks.json +0 -0
  45. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/schemas/users.json +0 -0
  46. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana/schemas/workspaces.json +0 -0
  47. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana.egg-info/dependency_links.txt +0 -0
  48. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana.egg-info/entry_points.txt +0 -0
  49. {tap-asana-2.2.0 → tap_asana-2.4.0}/tap_asana.egg-info/top_level.txt +0 -0
  50. {tap-asana-2.2.0 → tap_asana-2.4.0}/tests/test_discovery.py +0 -0
  51. {tap-asana-2.2.0 → tap_asana-2.4.0}/tests/test_interrupted_sync.py +0 -0
@@ -0,0 +1,22 @@
1
+ Metadata-Version: 2.4
2
+ Name: tap-asana
3
+ Version: 2.4.0
4
+ Summary: Singer.io tap for extracting Asana data
5
+ Home-page: http://github.com/singer-io/tap-asana
6
+ Author: Stitch
7
+ Classifier: Programming Language :: Python :: 3 :: Only
8
+ License-File: LICENSE
9
+ Requires-Dist: asana==5.1.0
10
+ Requires-Dist: requests==2.32.4
11
+ Requires-Dist: singer-python==6.1.1
12
+ Provides-Extra: test
13
+ Requires-Dist: pylint; extra == "test"
14
+ Provides-Extra: dev
15
+ Requires-Dist: ipdb; extra == "dev"
16
+ Dynamic: author
17
+ Dynamic: classifier
18
+ Dynamic: home-page
19
+ Dynamic: license-file
20
+ Dynamic: provides-extra
21
+ Dynamic: requires-dist
22
+ Dynamic: summary
@@ -13,6 +13,7 @@ This tap:
13
13
  - [Projects](https://developers.asana.com/docs/projects)
14
14
  - [Sections](https://developers.asana.com/docs/sections)
15
15
  - [Stories](https://developers.asana.com/docs/stories)
16
+ - [Subtasks](https://developers.asana.com/reference/getsubtasksfortask)
16
17
  - [Tags](https://developers.asana.com/docs/tags)
17
18
  - [Tasks](https://developers.asana.com/docs/tasks)
18
19
  - [Teams](https://developers.asana.com/docs/teams)
@@ -3,24 +3,23 @@ from setuptools import setup
3
3
 
4
4
  setup(
5
5
  name="tap-asana",
6
- version="2.2.0",
6
+ version="2.4.0",
7
7
  description="Singer.io tap for extracting Asana data",
8
8
  author="Stitch",
9
9
  url="http://github.com/singer-io/tap-asana",
10
10
  classifiers=["Programming Language :: Python :: 3 :: Only"],
11
11
  py_modules=["tap_asana"],
12
12
  install_requires=[
13
- "asana==3.1.0",
14
- 'singer-python==5.13.0'
13
+ "asana==5.1.0",
14
+ "requests==2.32.4",
15
+ "singer-python==6.1.1"
15
16
  ],
16
17
  extras_require={
17
- 'test': [
18
- 'pylint',
19
- 'requests==2.20.0',
20
- 'nose'
18
+ "test": [
19
+ "pylint"
21
20
  ],
22
- 'dev': [
23
- 'ipdb'
21
+ "dev": [
22
+ "ipdb"
24
23
  ]
25
24
  },
26
25
  entry_points="""
@@ -28,7 +27,7 @@ setup(
28
27
  tap-asana=tap_asana:main
29
28
  """,
30
29
  packages=["tap_asana"],
31
- package_data = {
30
+ package_data={
32
31
  "schemas": ["tap_asana/schemas/*.json"]
33
32
  },
34
33
  include_package_data=True,
@@ -0,0 +1,67 @@
1
+ import asana
2
+ import singer
3
+ import requests
4
+
5
+ LOGGER = singer.get_logger()
6
+
7
+
8
+ """ Simple wrapper for Asana. """
9
+
10
+
11
+ # pylint: disable=too-many-positional-arguments
12
+ class Asana():
13
+ """Base class for tap-asana"""
14
+
15
+ def __init__(
16
+ self, client_id, client_secret, redirect_uri, refresh_token, access_token=None
17
+ ): # pylint: disable=too-many-arguments
18
+ self.client_id = client_id
19
+ self.client_secret = client_secret
20
+ self.redirect_uri = redirect_uri
21
+ self.refresh_token = refresh_token
22
+ self.access_token = access_token
23
+ self._client = self._access_token_auth()
24
+
25
+ def _access_token_auth(self):
26
+ """Check for access token"""
27
+ if self.access_token is None:
28
+ self.access_token = self.refresh_access_token()
29
+
30
+ if self.access_token:
31
+ try:
32
+ configuration = asana.Configuration()
33
+ configuration.access_token = self.access_token
34
+ return asana.ApiClient(configuration)
35
+ except asana.rest.ApiException as e:
36
+ LOGGER.error("Error creating Asana client: %s", e)
37
+ return None
38
+
39
+ def refresh_access_token(self):
40
+ """Get the access token using the refresh token"""
41
+ url = "https://app.asana.com/-/oauth_token"
42
+ payload = {
43
+ "grant_type": "refresh_token",
44
+ "client_id": self.client_id,
45
+ "client_secret": self.client_secret,
46
+ "redirect_uri": self.redirect_uri,
47
+ "refresh_token": self.refresh_token,
48
+ }
49
+
50
+ headers = {"Content-Type": "application/x-www-form-urlencoded"}
51
+
52
+ try:
53
+ response = requests.post(url, data=payload, headers=headers, timeout=30)
54
+
55
+ if response.status_code == 200:
56
+ LOGGER.debug("Access token refreshed successfully.")
57
+ if "access_token" in response.json():
58
+ self.access_token = response.json()["access_token"]
59
+ return response.json()["access_token"]
60
+ return None
61
+ except requests.exceptions.RequestException as e:
62
+ LOGGER.error("Failed to refresh access token: %s", e)
63
+ return None
64
+
65
+ @property
66
+ def client(self):
67
+ return self._client
@@ -466,7 +466,7 @@
466
466
  ]
467
467
  }
468
468
  }
469
- }
469
+ }
470
470
  }
471
471
  }
472
472
  },
@@ -645,7 +645,7 @@
645
645
  "string"
646
646
  ]
647
647
  }
648
- }
648
+ }
649
649
  },
650
650
  "custom_fields": {
651
651
  "type": [
@@ -872,6 +872,57 @@
872
872
  "null",
873
873
  "boolean"
874
874
  ]
875
+ },
876
+ "archived": {
877
+ "type": [
878
+ "null",
879
+ "boolean"
880
+ ]
881
+ },
882
+ "default_access_level": {
883
+ "type": [
884
+ "null",
885
+ "string"
886
+ ]
887
+ },
888
+ "privacy_setting": {
889
+ "type": [
890
+ "null",
891
+ "string"
892
+ ]
893
+ },
894
+ "project_templates": {
895
+ "type": [
896
+ "null",
897
+ "array"
898
+ ],
899
+ "items": {
900
+ "type": [
901
+ "null",
902
+ "object"
903
+ ],
904
+ "additionalProperties": false,
905
+ "properties": {
906
+ "gid": {
907
+ "type": [
908
+ "null",
909
+ "string"
910
+ ]
911
+ },
912
+ "resource_type": {
913
+ "type": [
914
+ "null",
915
+ "string"
916
+ ]
917
+ },
918
+ "name": {
919
+ "type": [
920
+ "null",
921
+ "string"
922
+ ]
923
+ }
924
+ }
925
+ }
875
926
  }
876
927
  }
877
928
  }
@@ -1218,6 +1218,12 @@
1218
1218
  "null",
1219
1219
  "string"
1220
1220
  ]
1221
+ },
1222
+ "new_approval_status_updated": {
1223
+ "type": [
1224
+ "null",
1225
+ "string"
1226
+ ]
1221
1227
  }
1222
1228
  }
1223
1229
  }