Skip to content
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

Little improvements #15

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 24 additions & 20 deletions ClockifyAPI.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ def getTasksOnProject(self, workspace, projectName):
self._loadAdmin()

wsId = self.getWorkspaceID(workspace)
pId = self.getProjectID(projectName, workspace)
pId = self.get_project_id(projectName, workspace)

url = self.url + "/workspaces/%s/projects/%s/tasks" % (wsId, pId)
self.pTasks = self.multiGetRequest(url)
Expand Down Expand Up @@ -303,16 +303,16 @@ def getClientID(self, client, workspace, skipCliQuery=False):
raise RuntimeError("Client %s not found in workspace %s" % (client, workspace))
return clId

def getProjects(self, workspace, skipPrjQuery=False):
if self._syncProjects == True:
curUser = self._loadedUserEmail
def getProjects(self, workspace_name: str, skipPrjQuery=False):
if self._syncProjects:
cur_user = self._loadedUserEmail
self.projects = []

for user in self._APIusers:
self.logger.info("synchronizing clockify projects for user %s..." % user["email"])
self._loadUser(user["email"])

wsId = self.getWorkspaceID(workspace)
wsId = self.getWorkspaceID(workspace_name)
url = self.url + "/workspaces/%s/projects" % wsId
projects = self.multiGetRequest(url)
self.projects.extend(projects)
Expand All @@ -321,7 +321,7 @@ def getProjects(self, workspace, skipPrjQuery=False):
f = open("clockify_projects.json", "w")
f.write(json.dumps(self.projects, indent=2))
f.close()
self._loadUser(curUser)
self._loadUser(cur_user)
self._syncProjects = False

return self.projects
Expand Down Expand Up @@ -351,19 +351,23 @@ def getWorkspaceProjects(self, workspace, skipPrjQuery=False):

return self.projects

def getProjectID(self, project, workspace, skipPrjQuery=False):
pId = None
if skipPrjQuery:
def get_project(self, project_name: str, workspace_name: str, skip_prj_query=False):
if skip_prj_query:
projects = self.projects
else:
projects = self.getProjects(workspace, skipPrjQuery)
projects = self.getProjects(workspace_name, skip_prj_query)

project_candidates = []
for project in projects:
if project_name == project["name"]:
project_candidates.append(project)

if len(project_candidates) == 1:
return project_candidates[0]
raise ValueError(f"project {project_name} not found or multiple projects with same name found")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tohle bych rozdelil na dve chyby.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No jasně ale tak jako ten kód na spoustu větších problémů tak zas další if se mi řešit nechtěl.


for p in projects:
if p["name"] == project:
pId = p["id"]
if pId == None:
raise RuntimeError("Project %s not found in workspace %s" % (project, workspace))
return pId
def get_project_id(self, project_name, workspace, skip_prj_query=False):
return self.get_project(project_name, workspace, skip_prj_query)["id"]

def getUsers(self, workspace):
if self._syncUsers == True:
Expand Down Expand Up @@ -669,7 +673,7 @@ def addEntry(self, start, description, projectName, userMail, workspace,
url = self.url + "/workspaces/%s/time-entries" % wsId

if projectName != None:
projectId = self.getProjectID(projectName, workspace, skipPrjQuery=self._syncProjects)
projectId = self.get_project_id(projectName, workspace, skip_prj_query=self._syncProjects)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proc neni _syncProjects take prejmenvoana?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

protoze je toho k prejmenovani milion :D asi bych

if taskName != None:
pTasks = self.getTasksOnProject(workspace, projectName)
taskId = self.getTaskIdFromTasks(taskName, pTasks)
Expand Down Expand Up @@ -770,7 +774,7 @@ def getTimeEntryForUser(self, userMail, workspace, description,
uId = self.userID

if projectName != None:
prjID = self.getProjectID(projectName, workspace)
prjID = self.get_project_id(projectName, workspace)
if start != None:
start = start.strftime('%Y-%m-%dT%H:%M:%SZ')

Expand All @@ -795,7 +799,7 @@ def getTimeEntryForUser(self, userMail, workspace, description,

def archiveProject(self, projectName, workspace, skipPrjQuery=False):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tady skipPrjQuery a projectName nejsou moc Python style

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jako souhlas jen jsem začal pomalu přejmenovat a nechtělo se mi to dělat celý na to teď nemám čas

wsId = self.getWorkspaceID(workspace)
pID = self.getProjectID(projectName, workspace, skipPrjQuery=skipPrjQuery)
pID = self.get_project_id(projectName, workspace, skip_prj_query=skipPrjQuery)
url = "https://api.clockify.me/api/workspaces/%s/projects/%s/archive" % (wsId, pID)
rv = self._request(url, typ="GET")
if rv.status_code == 200:
Expand Down Expand Up @@ -841,7 +845,7 @@ def deleteEntry(self, entryID, workspace):

def deleteProject(self, projectName, workspace, skipPrjQuery=False):
wsId = self.getWorkspaceID(workspace)
projectID = self.getProjectID(projectName, workspace, skipPrjQuery)
projectID = self.get_project_id(projectName, workspace, skipPrjQuery)
url = self.url + "/workspaces/%s/projects/%s" % (wsId, projectID)
rv = self._request(url, typ="DELETE")
if rv.ok:
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CONDA_ENV=clockify-automation

conda-create:
conda env create -f conda.yml --name $(CONDA_ENV)
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ Credits to Markus Proeller, [email protected].

## Setup

* Create virtual env: `python -m venv venv` and activate it: `. ./venv/bin/activate `.
* Install requirements: `pip install -r requirements.txt`.
* Create virtual env in conda, use `make conda-create` then activate the environment via `conda activate clockify-automation`
* Set proper values in `config.json`, use `config_example.json` as a base.
* Run it: `python main.py`

Expand Down
20 changes: 20 additions & 0 deletions conda.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: txmatching
channels:
- conda-forge
dependencies:
- autopep8=2.0.0
- pip=22.3.1
- python=3.10.5
- pip:
- arrow==0.17.0
- certifi==2020.12.5
- chardet==4.0.0
- click==7.1.2
- idna==2.10
- python-dateutil==2.8.1
- pytz==2020.5
- requests==2.25.1
- six==1.15.0
- slumber==0.7.1
- TogglPy==0.1.1
- urllib3==1.26.5
12 changes: 9 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def main():
)

clockify = ClockifyAPI(clockify_settings.token, clockify_settings.email, reqTimeout=1)
clockify.getProjects(workspace=clockify_settings.workspace)
clockify.getProjects(workspace_name=clockify_settings.workspace)

toggle_base_url = 'https://api.track.toggl.com/api/v9'

Expand Down Expand Up @@ -177,8 +177,14 @@ def main():

tags = [tag.strip() for tag in row['tags'] if tag.strip() != '']

# tag billable if there's a tag billable
billable = 'billable' in tags
# tag billable if there's a tag else set default for the project
project = clockify.get_project(row['project_name'], clockify_settings.workspace)
if 'billable' in tags:
billable = True
elif 'non-billable' in tags:
billable = False
else:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hele to bych nedelal, podle me kdyz tam neni explicitne billable tag, tak to chceme jako non-billable. Respektive, ja toggle takhle pouzivam...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no takhle funguje clockify, ze kdyz je projekt jako celek neco tak podle toho se urci default.

ja takhle jsem zvyklej a dost mi to dava smysl, pro me je opruz pridavat furt billable vsude a prave mi vyhovuje ze vyuzivam toho, co je default na danym projektu.

ono je problem ze ty v podstate nikdy billable veci nemas, kdezto ja sem tam jo. Rekl bych ze aby obecne byl ten tool uzitecnej pro prumernyho mild blue cloveka, tak je moje reseni lepsi.

Ale pro tebe konkretne mozna chces mit ten case ze by default je vsechno non-billable i na billable projektech.

Tak tam asi muzeme pridat nejaky flag do configu no :D.

billable = project["billable"]
# remove billable and non-billable tags as we don't need them anymore
tags = [tag for tag in tags if tag not in {'non-billable', 'billable'}]

Expand Down