8000 feat: Org parameter can be specified as ID, Name or Organization Obje… · igsgd/influxdb-client-python@856cca4 · GitHub
[go: up one dir, main page]

Skip to content

Commit 856cca4

Browse files
authored
feat: Org parameter can be specified as ID, Name or Organization Object (influxdata#264)
1 parent 925e7cd commit 856cca4

File tree

10 files changed

+139
-44
lines changed

10 files changed

+139
-44
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
## 1.19.0 [unreleased]
22

3+
### Features
4+
1. [#264](https://github.com/influxdata/influxdb-client-python/pull/264): Org parameter can be specified as ID, Name or Organization Object [write, query]
5+
6+
### Deprecated
7+
1. [#264](https://github.com/influxdata/influxdb-client-python/pull/264): Deprecated `org_id` options BucketsApi.create_bucket in favor of `org` parameter
8+
39
## 1.18.0 [2021-06-04]
410

511
### Breaking Changes

examples/buckets_management.py

Copy file name to clipboard
Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,19 @@
99
"""
1010
url = "http://localhost:8086"
1111
token = "my-token"
12+
org = "my-org"
1213

1314
with InfluxDBClient(url=url, token=token) as client:
1415
buckets_api = client.buckets_api()
1516

16-
"""
17-
The Bucket API uses as a parameter the Organization ID. We have to retrieve ID by Organization API.
18-
"""
19-
org_name = "my-org"
20-
org = client.organizations_api().find_organizations(org=org_name)[0]
21-
2217
"""
2318
Create Bucket with retention policy set to 3600 seconds and name "bucket-by-python"
2419
"""
2520
print(f"------- Create -------\n")
2621
retention_rules = BucketRetentionRules(type="expire", every_seconds=3600)
2722
created_bucket = buckets_api.create_bucket(bucket_name="bucket-by-python",
2823
retention_rules=retention_rules,
29-
org_id=org.id)
24+
org=org)
3025
print(created_bucket)
3126

3227
"""

influxdb_client/client/bucket_api.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
All buckets have a retention policy, a duration of time that each data point persists.
55
A bucket belongs to an organization.
66
"""
7-
7+
import warnings
88

99
from influxdb_client import BucketsService, Bucket, PostBucketRequest
10+
from influxdb_client.client.util.helpers import get_org_query_param
1011

1112

1213
class BucketsApi(object):
@@ -18,15 +19,18 @@ def __init__(self, influxdb_client):
1819
self._buckets_service = BucketsService(influxdb_client.api_client)
1920

2021
def create_bucket(self, bucket=None, bucket_name=None, org_id=None, retention_rules=None,
21-
description=None) -> Bucket:
22+
description=None, org=None) -> Bucket:
2223
"""Create a bucket.
2324
24-
:param Bucket bucket: bucket to create (required)
25+
:param Bucket bucket: bucket to create
2526
:param bucket_name: bucket name
2627
:param description: bucket description
2728
:param org_id: org_id
2829
:param bucket_name: bucket name
2930
:param retention_rules: retention rules array or single BucketRetentionRules
31+
:param str, Organization org: specifies the organization for create the bucket;
32+
take the ID, Name or Organization;
33+
if it's not specified then is used default from client.org.
3034
:return: Bucket
3135
If the method is called asynchronously,
3236
returns the request thread.
@@ -41,11 +45,16 @@ def create_bucket(self, bucket=None, bucket_name=None, org_id=None, retention_ru
4145
else:
4246
rules.append(retention_rules)
4347

48+
if org_id is not None:
49+
warnings.warn("org_id is deprecated; use org", DeprecationWarning)
50+
4451
if bucket is None:
4552
bucket = PostBucketRequest(name=bucket_name,
4653
retention_rules=rules,
4754
description=description,
48-
org_id=self._influxdb_client.org if org_id is None else org_id)
55+
org_id=get_org_query_param(org=(org_id if org is None else org),
56+
client=self._influxdb_client,
57+
required_id=True))
4958

5059
return self._buckets_service.post_buckets(post_bucket_request=bucket)
5160

influxdb_client/client/query_api.py

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from influxdb_client.client.flux_csv_parser import FluxCsvParser, FluxSerializationMode
1717
from influxdb_client.client.flux_table import FluxTable, FluxRecord
1818
from influxdb_client.client.util.date_utils import get_date_helper
19+
from influxdb_client.client.util.helpers import get_org_query_param
1920

2021

2122
class QueryOptions(object):
@@ -51,14 +52,15 @@ def query_csv(self, query: str, org=None, dialect: Dialect = default_dialect, pa
5152
Execute the Flux query and return results as a CSV iterator. Each iteration returns a row of the CSV file.
5253
5354
:param query: a Flux query
54-
:param org: organization name (optional if already specified in InfluxDBClient)
55+
:param str, Organization org: specifies the organization for executing the query;
56+
take the ID, Name or Organization;
57+
if it's not specified then is used default from client.org.
5558
:param dialect: csv dialect format
5659
:param params: bind parameters
5760
:return: The returned object is an iterator. Each iteration returns a row of the CSV file
5861
(which can span multiple input lines).
5962
"""
60-
if org is None:
61-
org = self._influxdb_client.org
63+
org = self._org_param(org)
6264
response = self._query_api.post_query(org=org, query=self._create_query(query, dialect, params),
6365
async_req=False, _preload_content=False)
6466

@@ -69,13 +71,14 @@ def query_raw(self, query: str, org=None, dialect=default_dialect, params: dict
6971
Execute synchronous Flux query and return result as raw unprocessed result as a str.
7072
7173
:param query: a Flux query
72-
:param org: organization name (optional if already specified in InfluxDBClient)
74+
:param str, Organization org: specifies the organization for executing the query;
75+
take the ID, Name or Organization;
76+
if it's not specified then is used default from client.org.
7377
:param dialect: csv dialect format
7478
:param params: bind parameters
7579
:return: str
7680
"""
77-
if org is None:
78-
org = self._influxdb_client.org
81+
org = self._org_param(org)
7982
result = self._query_api.post_query(org=org, query=self._create_query(query, dialect, params), async_req=False,
8083
_preload_content=False)
8184

@@ -86,12 +89,13 @@ def query(self, query: str, org=None, params: dict = None) -> List['FluxTable']:
8689
Execute synchronous Flux query and return result as a List['FluxTable'].
8790
8891
:param query: the Flux query
89-
:param org: organization name (optional if already specified in InfluxDBClient)
92+
:param str, Organization org: specifies the organization for executing the query;
93+
take the ID, Name or Organization;
94+
if it's not specified then is used default from client.org.
9095
:param params: bind parameters
9196
:return:
9297
"""
93-
if org is None:
94-
org = self._influxdb_client.org
98+
org = self._org_param(org)
9599

96100
response = self._query_api.post_query(org=org, query=self._create_query(query, self.default_dialect, params),
97101
async_req=False, _preload_content=False, _return_http_data_only=False)
@@ -108,12 +112,13 @@ def query_stream(self, query: str, org=None, params: dict = None) -> Generator['
108112
Execute synchronous Flux query and return stream of FluxRecord as a Generator['FluxRecord'].
109113
110114
:param query: the Flux query
111-
:param org: organization name (optional if already specified in InfluxDBClient)
115+
:param str, Organization org: specifies the organization for executing the query;
116+
take the ID, Name or Organization;
117+
if it's not specified then is used default from client.org.
112118
:param params: bind parameters
113119
:return:
114120
"""
115-
if org is None:
116-
org = self._influxdb_client.org
121+
org = self._org_param(org)
117122

118123
response = self._query_api.post_query(org=org, query=self._create_query(query, self.default_dialect, params),
119124
async_req=False, _preload_content=False, _return_http_data_only=False)
@@ -129,7 +134,9 @@ def query_data_frame(self, query: str, org=None, data_frame_index: List[str] = N
129134
Note that if a query returns more then one table than the client generates a DataFrame for each of them.
130135
131136
:param query: the Flux query
132-
:param org: organization name (optional if already specified in InfluxDBClient)
137+
:param str, Organization org: specifies the organization for executing the query;
138+
take the ID, Name or Organization;
139+
if it's not specified then is used default from client.org.
133140
:param data_frame_index: the list of columns that are used as DataFrame index
134141
:param params: bind parameters
135142
:return:
@@ -153,13 +160,14 @@ def query_data_frame_stream(self, query: str, org=None, data_frame_index: List[s
153160
Note that if a query returns more then one table than the client generates a DataFrame for each of them.
154161
155162
:param query: the Flux query
156-
:param org: organization name (optional if already specified in InfluxDBClient)
163+
:param str, Organization org: specifies the organization for executing the query;
164+
take the ID, Name or Organization;
165+
if it's not specified then is used default from client.org.
157166
:param data_frame_index: the list of columns that are used as DataFrame index
158167
:param params: bind parameters
159168
:return:
160169
"""
161-
if org is None:
162-
org = self._influxdb_client.org
170+
org = self._org_param(org)
163171

164172
response = self._query_api.post_query(org=org, query=self._create_query(query, self.default_dialect, params),
165173
async_req=False, _preload_content=False, _return_http_data_only=False)
@@ -187,6 +195,9 @@ def _create_query(self, query, dialect=default_dialect, params: dict = None):
187195

188196
return q
189197

198+
def _org_param(self, org):
199+
return get_org_query_param(org=org, client=self._influxdb_client)
200+
190201
@staticmethod
191202
def _params_to_extern_ast(params: dict) -> List['OptionStatement']:
192203

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""Functions to share utility across client classes."""
2+
from influxdb_client.rest import ApiException
3+
4+
5+
def _is_id(value):
6+
"""
7+
Check if the value is valid InfluxDB ID.
8+
9+
:param value: to check
10+
:return: True if provided parameter is valid InfluxDB ID.
11+
"""
12+
if value and len(value) == 16:
13+
try:
14+
int(value, 16)
15+
return True
16+
except ValueError:
17+
return False
18+
return False
19+
20+
21+
def get_org_query_param(org, client, required_id=False):
22+
"""
23+
Get required type of Org query parameter.
24+
25+
:param str, Organization org: value provided as a parameter into API (optional)
26+
:param InfluxDBClient client: with default value for Org parameter
27+
:param bool required_id: true if the query param has to be a ID
28+
:return: request type of org query parameter or None
29+
"""
30+
_org = client.org if org is None else org
31+
if 'Organization' in type(_org).__name__:
32+
_org = _org.id
33+
if required_id and _org and not _is_id(_org):
34+
try:
35+
return client.organizations_api().find_organizations(org=_org)[0].id
36+
except ApiException:
37+
return None
38+
39+
return _org

influxdb_client/client/write_api.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from rx.subject import Subject
1717

1818
from influxdb_client import WritePrecision, WriteService
19+
from influxdb_client.client.util.helpers import get_org_query_param
1920
from influxdb_client.client.write.dataframe_serializer import data_frame_to_list_of_points
2021
from influxdb_client.client.write.point import Point, DEFAULT_WRITE_PRECISION
2122
from influxdb_client.client.write.retry import WritesRetry
@@ -221,8 +222,9 @@ def write(self, bucket: str, org: str = None,
221222
"""
222223
Write time-series data into InfluxDB.
223224
224-
:param str org: specifies the destination organization for writes; take either the ID or Name interchangeably;
225-
if both orgID and org are specified, org takes precedence. (required)
225+
:param str, Organization org: specifies the destination organization for writes;
226+
take the ID, Name or Organization;
227+
if it's not specified then is used default from client.org.
226228
:param str bucket: specifies the destination bucket for writes (required)
227229
:param WritePrecision write_precision: specifies the precision for the unix timestamps within
228230
the body line-protocol. The precision specified on a Point has precedes
@@ -231,8 +233,7 @@ def write(self, bucket: str, org: str = None,
231233
:key data_frame_measurement_name: name of measurement for writing Pandas DataFrame
232234
:key data_frame_tag_columns: list of DataFrame columns which are tags, rest columns will be fields
233235
"""
234-
if org is None:
235-
org = self._influxdb_client.org
236+
org = get_org_query_param(org=org, client=self._influxdb_client)
236237

237238
if self._point_settings.defaultTags and record is not None:
238239
for key, val in self._point_settings.defaultTags.items():

tests/base_test.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,15 @@ def tearDown(self) -> None:
4141

4242
def create_test_bucket(self):
4343
bucket_name = generate_bucket_name()
44-
bucket = self.buckets_api.create_bucket(bucket_name=bucket_name, org_id=self.my_organization.id,
44+
bucket = self.buckets_api.create_bucket(bucket_name=bucket_name, org=self.my_organization,
4545
description=bucket_name + "description")
4646
return bucket
4747

4848
def delete_test_bucket(self, bucket):
4949
return self.buckets_api.delete_bucket(bucket)
5050

5151
def find_my_org(self) -> Organization:
52-
org_api = influxdb_client.service.organizations_service.OrganizationsService(self.api_client)
53-
orgs = org_api.get_orgs()
54-
for org in orgs.orgs:
55-
if org.name == self.org:
56-
return org
52+
return self.client.organizations_api().find_organizations(org=self.org)[0]
5753

5854
@staticmethod
5955
def log(args):

tests/test_AuthorizationApi.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def test_createAuthorizationBucket(self):
8282
organization = self.client.organizations_api().create_organization(self.generate_name("Auth Organization"))
8383
bucket = self.client.buckets_api().create_bucket(bucket_name=self.generate_name("Auth Bucket"),
8484
retention_rules=BaseTest.retention_rule(),
85-
org_id=self.organization.id)
85+
org=self.organization)
8686
resource = PermissionResource(org_id=organization.id, type="buckets", id=bucket.id)
8787
create_bucket = Permission(action="read", resource=resource)
8888
delete_bucket = Permission(action="write", resource=resource)

tests/test_BucketsApi.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def test_create_delete_bucket(self):
2222
my_org = self.find_my_org()
2323

2424
bucket_name = generate_bucket_name()
25-
my_bucket = self.buckets_api.create_bucket(bucket_name=bucket_name, org_id=my_org.id)
25+
my_bucket = self.buckets_api.create_bucket(bucket_name=bucket_name, org=my_org)
2626
self.assertEqual(my_bucket.name, bucket_name)
2727
self.assertEqual(my_bucket.org_id, my_org.id)
2828
print(my_bucket)
@@ -41,7 +41,7 @@ def test_find_by_name(self):
4141
my_org = self.find_my_org()
4242

4343
bucket_name = generate_bucket_name()
44-
my_bucket = self.buckets_api.create_bucket(bucket_name=bucket_name, org_id=my_org.id)
44+
my_bucket = self.buckets_api.create_bucket(bucket_name=bucket_name, org=my_org)
4545

4646
bucket_by_name = self.buckets_api.find_bucket_by_name(bucket_name=my_bucket.name)
4747

@@ -58,7 +58,7 @@ def test_create_bucket_retention(self):
5858

5959
retention = BucketRetentionRules(type="expire", every_seconds=3600)
6060
desc = "bucket with retention"
61-
my_bucket = self.buckets_api.create_bucket(bucket_name=bucket_name, org_id=my_org.id,
61+
my_bucket = self.buckets_api.create_bucket(bucket_name=bucket_name, org=my_org,
6262
retention_rules=retention, description=desc)
6363

6464
self.assertEqual(my_bucket.description, desc)
@@ -76,7 +76,7 @@ def test_create_bucket_retention_list(self):
7676
retention.type = "expire"
7777
ret_list.append(retention)
7878

79-
my_bucket = self.buckets_api.create_bucket(bucket_name=bucket_name, org_id=my_org.id,
79+
my_bucket = self.buckets_api.create_bucket(bucket_name=bucket_name, org=my_org,
8080
retention_rules=ret_list)
8181

8282
self.assertEqual(my_bucket.name, bucket_name)
@@ -89,8 +89,8 @@ def test_pagination(self):
8989
size = len(buckets)
9090

9191
# create 2 buckets
92-
self.buckets_api.create_bucket(bucket_name=generate_bucket_name(), org_id=my_org.id)
93-
self.buckets_api.create_bucket(bucket_name=generate_bucket_name(), org_id=my_org.id)
92+
self.buckets_api.create_bucket(bucket_name=generate_bucket_name(), org=my_org)
93+
self.buckets_api.create_bucket(bucket_name=generate_bucket_name(), org=my_org)
9494

9595
buckets = self.buckets_api.find_buckets().buckets
9696
self.assertEqual(size + 2, len(buckets))

tests/test_Helpers.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from influxdb_client import InfluxDBClient, Organization
2+
# noinspection PyProtectedMember
3+
from influxdb_client.client.util.helpers import get_org_query_param, _is_id
4+
from tests.base_test import BaseTest
5+
6+
7+
class HelpersTest(BaseTest):
8+
9+
def test_is_id(self):
10+
self.assertTrue(_is_id("ffffffffffffffff"))
11+
self.assertTrue(_is_id("020f755c3c082000"))
12+
self.assertTrue(_is_id("ca55e77eca55e77e"))
13+
self.assertTrue(_is_id("02def021097c6000"))
14+
self.assertFalse(_is_id("gggggggggggggggg"))
15+
self.assertFalse(_is_id("abc"))
16+
self.assertFalse(_is_id("abcdabcdabcdabcd0"))
17+
self.assertFalse(_is_id("020f75"))
18+
self.assertFalse(_is_id("020f755c3c082000aaa"))
19+
self.assertFalse(_is_id(None))
20+
21+
def test_organization_as_query_param(self):
22+
organization = Organization(id="org-id", name="org-name")
23+
org = get_org_query_param(organization, self.client)
24+
self.assertEqual("org-id", org)
25+
26+
def test_required_id(self):
27+
org = get_org_query_param(None, self.client, required_id=True)
28+
self.assertEqual(self.my_organization.id, org)
29+
30+
def test_required_id_not_exist(self):
31+
org = get_org_query_param("not_exist_name", self.client, required_id=True)
32+
self.assertIsNone(org)
33+
34+
def test_both_none(self):
35+
self.client.close()
36+
self.client = InfluxDBClient(url=self.client.url, token="my-token")
37+
org = get_org_query_param(None, self.client)
38+
self.assertIsNone(org)

0 commit comments

Comments
 (0)
0