New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding Schedules Support Round 2 #48
Merged
Merged
Changes from 4 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
03e8ce3
added ability to query and delete schedules
shinchris 312a1c7
added ability to create and update schedules
shinchris b32a632
Merge branch 'development' of https://github.com/tableau/server-clien…
t8y8 0adb03f
Resubmitting #30 with a few changes.
t8y8 66e1793
Use new validation decorators
t8y8 0342bed
Refactoring intervals into their own classes - Round 1
t8y8 bb9ff8f
And fix pep8
t8y8 34457b3
Refactor intervals - Round 2. Added validation back
t8y8 f4490fb
Round 3, refactoring setters on the IntervalTypes. Import cleanup
t8y8 79271a1
Fix sample
t8y8 b710d9d
Round 4. Fully remove IntervalItem base class. Now it's just an enum …
t8y8 46cc1d0
Minor cleanup
t8y8 fd17154
Respond to CR feedback.
t8y8 371b6f9
Final round of cleanup, I think
t8y8 28ebb9e
Remove frequency and interval_occurence from public API
t8y8 c330687
More cleanup
t8y8 d7add3a
Move the interval-occurence tuple logic into a function just for the …
t8y8 File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#### | ||
# This script demonstrates how to create schedules using the Tableau | ||
# Server Client. | ||
# | ||
# To run the script, you must have installed Python 2.7.9 or later. | ||
#### | ||
|
||
|
||
import argparse | ||
import getpass | ||
import logging | ||
|
||
from datetime import time | ||
|
||
import tableauserverclient as TSC | ||
|
||
|
||
def main(): | ||
|
||
parser = argparse.ArgumentParser(description='Creates sample schedules for each type of frequency.') | ||
parser.add_argument('--server', '-s', required=True, help='server address') | ||
parser.add_argument('--username', '-u', required=True, help='username to sign into server') | ||
parser.add_argument('--logging-level', '-l', choices=['debug', 'info', 'error'], default='error', | ||
help='desired logging level (set to error by default)') | ||
args = parser.parse_args() | ||
|
||
password = getpass.getpass("Password: ") | ||
|
||
# Set logging level based on user input, or error by default | ||
logging_level = getattr(logging, args.logging_level.upper()) | ||
logging.basicConfig(level=logging_level) | ||
|
||
tableau_auth = TSC.TableauAuth(args.username, password) | ||
server = TSC.Server(args.server) | ||
with server.auth.sign_in(tableau_auth): | ||
# Hourly Schedule | ||
hourly_interval = TSC.IntervalItem.create_hourly(time(2, 30), time(23, 0), TSC.IntervalItem.Occurrence.Hours, 2) | ||
hourly_schedule = TSC.ScheduleItem("Hourly-Schedule", 50, TSC.ScheduleItem.Type.Extract, | ||
TSC.ScheduleItem.ExecutionOrder.Parallel, hourly_interval) | ||
hourly_schedule = server.schedules.create(hourly_schedule) | ||
print("Hourly schedule created (ID: {}).".format(hourly_schedule.id)) | ||
|
||
# Daily Schedule | ||
daily_interval = TSC.IntervalItem.create_daily(time(5)) | ||
daily_schedule = TSC.ScheduleItem("Daily-Schedule", 60, TSC.ScheduleItem.Type.Subscription, | ||
TSC.ScheduleItem.ExecutionOrder.Serial, daily_interval) | ||
daily_schedule = server.schedules.create(daily_schedule) | ||
print("Daily schedule created (ID: {}).".format(daily_schedule.id)) | ||
|
||
# Weekly Schedule | ||
weekly_interval = TSC.IntervalItem.create_weekly(time(19, 15), TSC.IntervalItem.Day.Monday, | ||
TSC.IntervalItem.Day.Wednesday, TSC.IntervalItem.Day.Friday) | ||
weekly_schedule = TSC.ScheduleItem("Weekly-Schedule", 70, TSC.ScheduleItem.Type.Extract, | ||
TSC.ScheduleItem.ExecutionOrder.Serial, weekly_interval) | ||
weekly_schedule = server.schedules.create(weekly_schedule) | ||
print("Weekly schedule created (ID: {}).".format(weekly_schedule.id)) | ||
|
||
# Monthly Schedule | ||
monthly_interval = TSC.IntervalItem.create_monthly(time(23, 30), 15) | ||
monthly_schedule = TSC.ScheduleItem("Monthly-Schedule", 80, TSC.ScheduleItem.Type.Subscription, | ||
TSC.ScheduleItem.ExecutionOrder.Parallel, monthly_interval) | ||
monthly_schedule = server.schedules.create(monthly_schedule) | ||
print("Monthly schedule created (ID: {}).".format(monthly_schedule.id)) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import xml.etree.ElementTree as ET | ||
from datetime import datetime | ||
from .. import NAMESPACE | ||
|
||
|
||
class IntervalItem(object): | ||
class Frequency: | ||
Hourly = "Hourly" | ||
Daily = "Daily" | ||
Weekly = "Weekly" | ||
Monthly = "Monthly" | ||
|
||
class Occurrence: | ||
Hours = "Hours" | ||
Minutes = "Minutes" | ||
WeekDay = "weekDay" | ||
MonthDay = "monthDay" | ||
|
||
class Day: | ||
Sunday = "Sunday" | ||
Monday = "Monday" | ||
Tuesday = "Tuesday" | ||
Wednesday = "Wednesday" | ||
Thursday = "Thursday" | ||
Friday = "Friday" | ||
Saturday = "Saturday" | ||
LastDay = "LastDay" | ||
|
||
def __init__(self, frequency, interval, start_time, end_time=None): | ||
self.end_time = end_time | ||
self.frequency = frequency | ||
self.interval = interval | ||
self.start_time = start_time | ||
|
||
@staticmethod | ||
def _validate_time(t): | ||
units_of_time = {"hour", "minute", "second"} | ||
|
||
if not any(hasattr(t, unit) for unit in units_of_time): | ||
error = "Invalid time object defined." | ||
raise ValueError(error) | ||
|
||
@classmethod | ||
def create_hourly(cls, start_time, end_time, interval_occurrence, interval_value): | ||
if interval_occurrence != IntervalItem.Occurrence.Hours and \ | ||
interval_occurrence != IntervalItem.Occurrence.Minutes: | ||
error = "Invalid interval type defined: {}.".format(interval_occurrence) | ||
raise ValueError(error) | ||
elif interval_occurrence == IntervalItem.Occurrence.Hours and interval_value not in [1, 2, 4, 6, 8, 12]: | ||
error = "Invalid hour value defined: {}.".format(interval_value) | ||
raise ValueError(error) | ||
elif interval_occurrence == IntervalItem.Occurrence.Minutes and interval_value not in [15, 30]: | ||
error = "Invalid minute value defined: {}".format(interval_value) | ||
raise ValueError(error) | ||
|
||
cls._validate_time(start_time) | ||
cls._validate_time(end_time) | ||
interval = [(interval_occurrence.lower(), str(interval_value))] | ||
return cls(IntervalItem.Frequency.Hourly, interval, start_time, end_time) | ||
|
||
@classmethod | ||
def create_daily(cls, start_time): | ||
cls._validate_time(start_time) | ||
return cls(IntervalItem.Frequency.Daily, None, start_time) | ||
|
||
@classmethod | ||
def create_weekly(cls, start_time, *interval_value): | ||
interval = [] | ||
for day in interval_value: | ||
if not hasattr(IntervalItem.Day, day): | ||
error = "Invalid week day defined: {}.".format(day) | ||
raise ValueError(error) | ||
interval.append((IntervalItem.Occurrence.WeekDay, day)) | ||
cls._validate_time(start_time) | ||
return cls(IntervalItem.Frequency.Weekly, interval, start_time) | ||
|
||
@classmethod | ||
def create_monthly(cls, start_time, interval_value): | ||
if (interval_value < 1 or interval_value > 31) and interval_value != IntervalItem.Day.LastDay: | ||
error = "Invalid interval value defined for a monthly frequency: {}.".format(interval_value) | ||
raise ValueError(error) | ||
interval = [(IntervalItem.Occurrence.MonthDay, str(interval_value))] | ||
cls._validate_time(start_time) | ||
return cls(IntervalItem.Frequency.Monthly, interval, start_time) | ||
|
||
@classmethod | ||
def from_response(cls, resp, frequency): | ||
cls.from_xml_element(ET.fromstring(resp), frequency) | ||
|
||
@classmethod | ||
def from_xml_element(cls, parsed_response, frequency): | ||
start_time = parsed_response.get("start", None) | ||
start_time = datetime.strptime(start_time, "%H:%M:%S").time() | ||
end_time = parsed_response.get("end", None) | ||
if end_time is not None: | ||
end_time = datetime.strptime(end_time, "%H:%M:%S").time() | ||
interval_elems = parsed_response.findall(".//t:intervals/t:interval", namespaces=NAMESPACE) | ||
interval = [] | ||
for interval_elem in interval_elems: | ||
interval.extend(interval_elem.attrib.items()) | ||
return cls(frequency, interval, start_time, end_time) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yikes, I need to update these now :)
(I wonder if we can find a way to run these, either in a local task, or in travis somehow)