Skip to content

Commit 7c514b3

Browse files
authored
Access token created on fix (#143)
* * Fix setting of the created_on attribute on AccessToken * Add support for show.problems on TransactionAsyncResponse * Fix a number of issues with the examples * Fix a few embarrassing code formatting issues * add missing files to changeset * add logging to _request_access_token * remove spurious warning log when tokens.json file does not exist * add notes to CHANGELOG.md
1 parent ea9d5e8 commit 7c514b3

File tree

10 files changed

+43
-34
lines changed

10 files changed

+43
-34
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## v0.6.19
4+
5+
* Fix setting of created_on attribute on AccessToken
6+
* Fix show.problems on TransactionAsyncResponse
7+
* add logging to _request_access_token
8+
* remove spurious warning log when tokens.json file does not exist
9+
* Fix several problems with the examples
10+
311
## v0.6.18
412

513
* Added retry mechanism for the authentication flow.

examples/create_engine.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
def run(engine: str, size: str, profile: str):
2424
cfg = config.read(profile=profile)
2525
ctx = api.Context(**cfg)
26-
api.create_engine(ctx, engine, size)
26+
api.create_engine_wait(ctx, engine, size)
2727
print(json.dumps(api.get_engine(ctx, engine), indent=2))
2828

2929

examples/run-all

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ python3 ./list_databases.py --state=CREATED
2626
python3 ./list_databases.py --state=NONSENSE
2727
python3 ./list_edbs.py $DATABASE $ENGINE
2828
python3 ./list_models.py $DATABASE $ENGINE
29-
python3 ./get_model.py $DATABASE $ENGINE stdlib
29+
python3 ./get_model.py $DATABASE $ENGINE "rel/stdlib"
3030

3131
# run query
3232
QUERY="x, x^2, x^3, x^4 from x in {1; 2; 3; 4; 5}"
33-
python3 ./run_query.py $DATABASE $ENGINE "$QUERY"
34-
python3 ./run_query.py $DATABASE $ENGINE "$QUERY" --readonly
33+
python3 ./execute.py $DATABASE $ENGINE "$QUERY"
34+
python3 ./execute.py $DATABASE $ENGINE "$QUERY" --readonly
3535
python3 ./show_results.py $DATABASE $ENGINE
3636
python3 ./show_problems.py $DATABASE $ENGINE
3737

@@ -44,16 +44,16 @@ python3 ./list_models.py $DATABASE $ENGINE
4444

4545
# load_csv
4646
python3 ./load_csv.py $DATABASE $ENGINE sample.csv -r sample_csv
47-
python3 ./run_query.py $DATABASE $ENGINE sample_csv
47+
python3 ./execute.py $DATABASE $ENGINE sample_csv
4848
python3 ./load_csv.py $DATABASE $ENGINE sample_no_header.csv --header-row=0 -r sample_no_header_csv
49-
python3 ./run_query.py $DATABASE $ENGINE sample_no_header_csv
49+
python3 ./execute.py $DATABASE $ENGINE sample_no_header_csv
5050
python3 ./load_csv.py $DATABASE $ENGINE sample_alt_syntax.csv --delim="|" --quotechar="'" -r sample_alt_syntax_csv
51-
python3 ./run_query.py $DATABASE $ENGINE sample_alt_syntax_csv
51+
python3 ./execute.py $DATABASE $ENGINE sample_alt_syntax_csv
5252
python3 ./list_edbs.py $DATABASE $ENGINE
5353

5454
# load_json
5555
python3 ./load_json.py $DATABASE $ENGINE sample.json -r sample_json
56-
python3 ./run_query.py $DATABASE $ENGINE sample_json
56+
python3 ./execute.py $DATABASE $ENGINE sample_json
5757
python3 ./list_edbs.py $DATABASE $ENGINE
5858

5959
# clone database

examples/show_problems.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
def run(database: str, engine: str, profile: str):
2424
cfg = config.read(profile=profile)
2525
ctx = api.Context(**cfg)
26-
rsp = api.query(ctx, database, engine, "def output = **nonsense**")
26+
rsp = api.exec(ctx, database, engine, "def output = **nonsense**")
2727
show.problems(rsp)
2828

2929

examples/show_results.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
def run(database: str, engine: str, profile: str):
2525
cfg = config.read(profile=profile)
2626
ctx = api.Context(**cfg)
27-
rsp = api.query(ctx, database, engine, "def output = 'a'; 'b'; 'c'")
27+
rsp = api.exec(ctx, database, engine, "def output = 'a'; 'b'; 'c'")
2828
show.results(rsp)
2929

3030

railib/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
__version_info__ = (0, 6, 18)
15+
__version_info__ = (0, 6, 19)
1616
__version__ = ".".join(map(str, __version_info__))

railib/api.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,6 @@ def __init__(
157157

158158

159159
# Transaction async response class
160-
161-
162160
class TransactionAsyncResponse:
163161
def __init__(
164162
self,
@@ -184,8 +182,6 @@ def __str__(self):
184182

185183

186184
# Transaction async file class
187-
188-
189185
class TransactionAsyncFile:
190186
def __init__(
191187
self,
@@ -238,8 +234,6 @@ def _get_collection(ctx, path: str, key=None, **kwargs):
238234

239235

240236
# Parse "multipart/form-data" response
241-
242-
243237
def _parse_multipart_form(
244238
content_type: str, content: bytes
245239
) -> List[TransactionAsyncFile]:
@@ -268,8 +262,6 @@ def _parse_multipart_form(
268262

269263

270264
# Parse TransactionAsync response
271-
272-
273265
def _parse_transaction_async_response(
274266
files: List[TransactionAsyncFile],
275267
) -> TransactionAsyncResponse:

railib/credentials.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ class Credentials(ABC):
3232

3333
# Represents an OAuth access token.
3434
class AccessToken:
35-
def __init__(self, access_token: str, scope: str, expires_in: int, created_on: float = time.time()):
35+
def __init__(self, access_token: str, scope: str, expires_in: int, created_on: float = None):
3636
self.access_token = access_token
3737
self.scope = scope
3838
self.expires_in = expires_in
39-
self.created_on = created_on
39+
self.created_on = created_on or time.time()
4040

4141
def is_expired(self):
4242
return (

railib/rest.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,14 @@ def _cache_file() -> str:
128128

129129
# Read oauth cache
130130
def _read_cache() -> dict:
131+
filename = _cache_file()
132+
if not path.exists(filename):
133+
return {}
131134
try:
132-
with open(_cache_file(), 'r') as cache:
135+
with open(filename, 'r') as cache:
133136
return json.loads(cache.read())
134137
except Exception as e:
135-
logger.warning(f'Failed to read token cache {_cache_file()}: {e}')
138+
logger.error(f"can't read token cache {filename}: {e}")
136139
return {}
137140

138141

@@ -150,7 +153,6 @@ def _write_token_cache(creds: ClientCredentials):
150153
try:
151154
cache = _read_cache()
152155
cache[creds.client_id] = creds.access_token
153-
154156
with open(_cache_file(), 'w') as f:
155157
f.write(json.dumps(cache, default=vars))
156158
except Exception as e:
@@ -169,6 +171,13 @@ def _get_access_token(ctx: Context, url: str) -> AccessToken:
169171
return creds.access_token.access_token
170172

171173

174+
def _log_request_response(req, rsp):
175+
content_type = req.headers["Content-Type"] if "Content-Type" in req.headers else ""
176+
agent = req.headers["User-Agent"] if "User-Agent" in req.headers else ""
177+
request_id = rsp.headers["X-Request-ID"] if "X-Request-ID" in rsp.headers else ""
178+
logger.debug(f"{rsp._method} HTTP/{rsp.version} {content_type} {rsp.url} {rsp.status} {agent} {request_id}")
179+
180+
172181
def _request_access_token(ctx: Context, url: str) -> AccessToken:
173182
creds = ctx.credentials
174183
assert isinstance(creds, ClientCredentials)
@@ -195,9 +204,9 @@ def _request_access_token(ctx: Context, url: str) -> AccessToken:
195204
)
196205
_print_request(req)
197206
with _urlopen_with_retry(req, ctx.retries) as rsp:
207+
_log_request_response(req, rsp)
198208
result = json.loads(rsp.read())
199209
token = result.get(ACCESS_KEY_TOKEN_KEY, None)
200-
201210
if token is not None:
202211
expires_in = result.get(EXPIRES_IN_KEY, None)
203212
scope = result.get(SCOPE, None)
@@ -230,7 +239,7 @@ def _urlopen_with_retry(req: Request, retries: int = 0):
230239
return urlopen(req)
231240
except (URLError, ConnectionError) as e:
232241
logger.warning(f"URL/Connection error occured {req.full_url} (attempt {attempt + 1}/{attempts}). Error message: {str(e)}")
233-
242+
234243
if attempt == attempts - 1:
235244
logger.error(f"Failed to connect to {req.full_url} after {attempts} attempt{'s' if attempts > 1 else ''}")
236245
raise e
@@ -246,12 +255,7 @@ def request(ctx: Context, method: str, url: str, headers={}, data=None, **kwargs
246255
req = _authenticate(ctx, req)
247256
_print_request(req)
248257
rsp = _urlopen_with_retry(req, ctx.retries)
249-
250-
# logging
251-
content_type = headers["Content-Type"] if "Content-Type" in headers else ""
252-
agent = headers["User-Agent"] if "User-Agent" in headers else ""
253-
request_id = rsp.headers["X-Request-ID"] if "X-Request-ID" in rsp.headers else ""
254-
logger.debug(f"{rsp._method} HTTP/{rsp.version} {content_type} {rsp.url} {rsp.status} {agent} {request_id}")
258+
_log_request_response(req, rsp)
255259
return rsp
256260

257261

railib/show.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,15 @@ def _show_rel(rsp: dict) -> None:
7474

7575

7676
# Print the problems in the given response dict.
77-
def problems(rsp: dict) -> None:
77+
def problems(rsp) -> None:
7878
if rsp is None:
7979
return
80-
problems = rsp.get("problems", None)
80+
if isinstance(rsp, dict): # v1 transaction
81+
problems = rsp.get("problems", None)
82+
elif isinstance(rsp, TransactionAsyncResponse):
83+
problems = rsp.problems
84+
else:
85+
raise ValueError("bad response type")
8186
if not problems:
8287
return
8388
for problem in problems:

0 commit comments

Comments
 (0)