├── __init__.py
├── emailer
├── __init__.py
├── aws_emailer
│ ├── __init__.py
│ └── email_with_attachment.py
├── gcp_emailer
│ ├── __init__.py
│ └── gcp_email.py
└── README.md
├── just_for_fun
├── qr_code
│ ├── images
│ │ ├── .gitkeep
│ │ ├── genesys.png
│ │ ├── vanessa.jpeg
│ │ ├── pycon_ireland.png
│ │ ├── devfestireland.png
│ │ ├── pycon_ireland_22.png
│ │ └── Genesys_square_logo.png
│ ├── qr_codes
│ │ ├── .gitkeep
│ │ ├── rounded.png
│ │ ├── standard.png
│ │ ├── with_image.png
│ │ ├── with_mask.png
│ │ ├── ronan_rounded.png
│ │ ├── ronan_standard.png
│ │ ├── ronan_with_image.png
│ │ ├── ronan_with_mask.png
│ │ ├── vanessa_rounded.png
│ │ ├── vanessa_standard.png
│ │ ├── vanessa_with_image.png
│ │ ├── vanessa_with_mask.png
│ │ ├── adf_builder_rounded.png
│ │ ├── adf_builder_standard.png
│ │ ├── adf_builder_with_mask.png
│ │ ├── jira_rest_api_rounded.png
│ │ ├── jirascripting_rounded.png
│ │ ├── adf_builder_with_image.png
│ │ ├── devfestireland_rounded.png
│ │ ├── devfestireland_standard.png
│ │ ├── jira_rest_api_standard.png
│ │ ├── jira_rest_api_with_mask.png
│ │ ├── jirascripting_standard.png
│ │ ├── jirascripting_with_mask.png
│ │ ├── devfestireland_with_image.png
│ │ ├── devfestireland_with_mask.png
│ │ ├── jira_rest_api_with_image.png
│ │ └── jirascripting_with_image.png
│ ├── .DS_Store
│ └── qr_code_production.py
├── file_access
│ ├── output
│ │ ├── example.csv
│ │ └── MOCK_DATA_WITH_PROJECT.csv
│ ├── .DS_Store
│ ├── input
│ │ ├── example.xlsx
│ │ ├── example.csv
│ │ └── MOCK_DATA.csv
│ ├── write_csv.py
│ ├── csv_read.py
│ ├── excel_read.py
│ └── adding_to_the_mock_data.py
├── .DS_Store
├── HTML
│ ├── json2html2pdf.pdf
│ ├── json2html.html
│ └── json_to_html.py
└── README.md
├── part_1_story_creation
├── reports
│ └── .gitkeep
├── README.md
├── part_1_same_story_for_every_project.py
├── part_2_same_story_for_every_project_assigned_to_a_user.py
├── part_3_same_story_for_every_project_assigned_to_project_lead.py
└── part_4_same_story_for_every_project_assigned_with_report.py
├── part_2_epic_creation
├── reports
│ └── .gitkeep
├── README.md
├── part_1_create_an_epic.py
├── part_2_create_many_linked_epics.py
└── part_3_create_many_linked_epics_with_record.py
├── src
├── __init__.py
└── jirascripting
│ ├── __init__.py
│ ├── auth_and_headers.py
│ ├── create_jira_epic.py
│ ├── get_assignable_users.py
│ ├── create_jira_issue.py
│ ├── create_jira_issue_with_parent.py
│ ├── create_fancy_jira_issue.py
│ └── helpers.py
├── part_3_creating_from_csv
├── input
│ ├── .gitkeep
│ ├── MOCK_DATA.csv
│ └── MOCK_DATA_WITH_PROJECT.csv
├── README.md
├── part_1_create_from_csv.py
├── part_2_create_fancy_from_csv.py
├── part_3_create_in_projects_defined_in_csv.py
└── _description_document.py
├── part_0_my_jira_cloud_instance
├── output
│ └── .gitkeep
├── README.md
└── get_to_know_your_jira_instance.py
├── part_4_creating_assigning_and_emailing
├── input
│ ├── .gitkeep
│ ├── devfestireland_with_image.png
│ ├── MOCK_DATA_WITH_PROJECT_3_lines.csv
│ ├── MOCK_DATA_WITH_PROJECT_6_lines.csv
│ └── MOCK_DATA_WITH_PROJECT.csv
├── reports
│ └── .gitkeep
├── README.md
├── _follow_up_email_body.py
├── part_5_completeness_percentage_sunburst.py
├── _email_body.py
├── _comment_document.py
├── part_3_follow_up_with_a_comment.py
├── part_4_follow_up_with_an_email.py
├── part_1_create_assign_email.py
├── _description_document.py
└── part_2_create_assign_email_prepaired_for_follow_up.py
├── .DS_Store
├── .env_template
├── CONTRIBUTING.md
├── requirements.txt
├── pyproject.toml
├── SECURITY.md
├── LICENSE
├── .github
└── workflows
│ └── codeql.yml
├── .gitignore
├── README.md
└── CODE_OF_CONDUCT.md
/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/emailer/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/emailer/aws_emailer/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/emailer/gcp_emailer/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/just_for_fun/qr_code/images/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/part_1_story_creation/reports/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/part_2_epic_creation/reports/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/__init__.py:
--------------------------------------------------------------------------------
1 | # this is a comment
--------------------------------------------------------------------------------
/part_3_creating_from_csv/input/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/part_0_my_jira_cloud_instance/output/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/jirascripting/__init__.py:
--------------------------------------------------------------------------------
1 | # this is a comment
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/input/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/reports/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/just_for_fun/file_access/output/example.csv:
--------------------------------------------------------------------------------
1 | I,love,Python,Hangouts
2 |
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/.DS_Store
--------------------------------------------------------------------------------
/just_for_fun/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/.DS_Store
--------------------------------------------------------------------------------
/.env_template:
--------------------------------------------------------------------------------
1 | # copy this file and save it as .env then fill in the values
2 | JIRA_EMAIL=
3 | API_KEY=
4 | BASE_URL=
5 |
--------------------------------------------------------------------------------
/just_for_fun/qr_code/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/.DS_Store
--------------------------------------------------------------------------------
/just_for_fun/HTML/json2html2pdf.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/HTML/json2html2pdf.pdf
--------------------------------------------------------------------------------
/just_for_fun/file_access/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/file_access/.DS_Store
--------------------------------------------------------------------------------
/just_for_fun/qr_code/images/genesys.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/images/genesys.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/images/vanessa.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/images/vanessa.jpeg
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/rounded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/rounded.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/standard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/standard.png
--------------------------------------------------------------------------------
/just_for_fun/file_access/input/example.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/file_access/input/example.xlsx
--------------------------------------------------------------------------------
/just_for_fun/qr_code/images/pycon_ireland.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/images/pycon_ireland.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/with_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/with_image.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/with_mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/with_mask.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/images/devfestireland.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/images/devfestireland.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/ronan_rounded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/ronan_rounded.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/images/pycon_ireland_22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/images/pycon_ireland_22.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/ronan_standard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/ronan_standard.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/ronan_with_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/ronan_with_image.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/ronan_with_mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/ronan_with_mask.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/vanessa_rounded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/vanessa_rounded.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/vanessa_standard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/vanessa_standard.png
--------------------------------------------------------------------------------
/just_for_fun/file_access/input/example.csv:
--------------------------------------------------------------------------------
1 | Name,Age,City,Job
2 | David,21,Dublin,Dev
3 | Mary,28,Galway,DevOps
4 | John,30,London,Security
5 | Ann,45,Leeds,Marketing
--------------------------------------------------------------------------------
/just_for_fun/qr_code/images/Genesys_square_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/images/Genesys_square_logo.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/vanessa_with_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/vanessa_with_image.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/vanessa_with_mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/vanessa_with_mask.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/adf_builder_rounded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/adf_builder_rounded.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/adf_builder_standard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/adf_builder_standard.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/adf_builder_with_mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/adf_builder_with_mask.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/jira_rest_api_rounded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jira_rest_api_rounded.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/jirascripting_rounded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jirascripting_rounded.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/adf_builder_with_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/adf_builder_with_image.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/devfestireland_rounded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/devfestireland_rounded.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/devfestireland_standard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/devfestireland_standard.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/jira_rest_api_standard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jira_rest_api_standard.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/jira_rest_api_with_mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jira_rest_api_with_mask.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/jirascripting_standard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jirascripting_standard.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/jirascripting_with_mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jirascripting_with_mask.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/devfestireland_with_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/devfestireland_with_image.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/devfestireland_with_mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/devfestireland_with_mask.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/jira_rest_api_with_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jira_rest_api_with_image.png
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_codes/jirascripting_with_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/just_for_fun/qr_code/qr_codes/jirascripting_with_image.png
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/input/devfestireland_with_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dren79/JiraScripting_public/HEAD/part_4_creating_assigning_and_emailing/input/devfestireland_with_image.png
--------------------------------------------------------------------------------
/just_for_fun/file_access/write_csv.py:
--------------------------------------------------------------------------------
1 | import csv
2 |
3 | data = ["I", "love", "Python", "Hangouts"]
4 |
5 | with open('output/example.csv', 'w') as file:
6 | writer = csv.writer(file)
7 | writer.writerow(data)
8 |
--------------------------------------------------------------------------------
/just_for_fun/file_access/csv_read.py:
--------------------------------------------------------------------------------
1 | import csv
2 |
3 | with open("input/example.csv") as infile:
4 | reader = csv.reader(infile, delimiter=",")
5 |
6 | next(reader, None)
7 |
8 | for row in reader:
9 | print(row)
10 | print(row[0])
11 | print(row[1])
12 |
--------------------------------------------------------------------------------
/part_2_epic_creation/README.md:
--------------------------------------------------------------------------------
1 | # JiraScripting - Epic Creation
2 |
3 | This section deals with the creation of Epics and how we start to logically collect issues.
4 |
5 | ### What is in this section? ###
6 |
7 | * Create an epic
8 | * Create many epics linked under and Uber Epic or Initiative
9 | * Continue keeping a report of actions taken
--------------------------------------------------------------------------------
/just_for_fun/README.md:
--------------------------------------------------------------------------------
1 | # JiraScripting - Just for Fun
2 |
3 | Not directly used by this repository but were used in presenting this repository
4 |
5 | ### What is in this section? ###
6 |
7 | * File Access - how to access different file types you may wish to import issues from
8 | * QR Code - create fancy QR codes from URL's
9 | * HTML - representing a JSON file as HTML
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contributions welcome via pull request.
2 | Add a directory following the naming convention including a descriptive title.
3 | If adding to the helpers.py file, please also add a docstring and a calling section in th if __name__ == "main": section.
4 |
5 | While not manditory to contribute, if you've found this repo useful and you have added to it, I would encourage you to do so.
6 |
--------------------------------------------------------------------------------
/just_for_fun/file_access/excel_read.py:
--------------------------------------------------------------------------------
1 | import os
2 | from openpyxl import load_workbook
3 |
4 | wb = load_workbook(filename=f"input/example.xlsx")
5 | sheet_names = wb.sheetnames
6 | ws = wb[sheet_names[0]]
7 |
8 | for row_num, row_val in enumerate(ws.iter_rows(min_row=2, max_row=ws.max_row), start=2):
9 | Name = row_val[0].value
10 | Age = row_val[1].value
11 | City = row_val[2].value
12 |
--------------------------------------------------------------------------------
/part_1_story_creation/README.md:
--------------------------------------------------------------------------------
1 | # JiraScripting - Story Creation
2 |
3 | This section deals with the most atomic action in Jira Cloud, creating an issue.
4 |
5 | ### What is in this section? ###
6 |
7 | * Creating an issue
8 | * Getting all projects using the method found in the helpers file
9 | * Using the assignable users JSON output
10 | * Introducing the concept of keeping a report of actions taken
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | pillow>=9.3.0
2 | qrcode==7.3.1
3 |
4 | defusedxml~=0.6.0
5 | future~=0.17.1
6 | ipython>=7.34.0
7 | pip>=21.3.1
8 | toml~=0.10.1
9 | Brotli~=1.0.9
10 | cryptography~=3.2
11 | py==1.11.0
12 | setuptools>=65.5.1
13 | docutils~=0.15.2
14 | requests~=2.31.0
15 | python-dotenv~=0.19.0
16 | retrying~=1.3.3
17 | botocore~=1.15.49
18 | boto3~=1.12.49
19 | sendgrid~=6.9.7
20 | openpyxl~=3.0.9
21 | json2html~=1.3.0
22 | pytz~=2019.3
23 | pandas~=1.3.2
24 | plotly~=5.3.1
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name="jirascripting"
3 | version='0.0.5'
4 | description='Methods for interacting with Jira Cloud'
5 | authors = [
6 | { name="David Renton", email="davidleerenton@gmail.com" },
7 | ]
8 | dependencies=["requests~=2.31.0", "python-dotenv~=0.19.0"]
9 | classifiers=[
10 | "Development Status :: 3 - Alpha",
11 | 'License :: OSI Approved :: MIT License',
12 | "Programming Language :: Python :: 3",
13 | 'Operating System :: OS Independent',
14 | ]
15 |
16 |
--------------------------------------------------------------------------------
/emailer/README.md:
--------------------------------------------------------------------------------
1 | # JiraScripting - Emailer
2 |
3 | Two directories for two cloud emailing offerings. AWS is implemented, GCP is a skeleton only
4 |
5 | ### What is in this section? ###
6 |
7 | * AWS emailer - this requires an active AWS account with the email address you wish to send emails from registered in SES.
8 | * The correct aws_access_key_id and aws_secret_access_key must be created and used to gain access.
9 | * Further instructions can be found here - https://docs.aws.amazon.com/ses/latest/dg/setting-up.html
10 | * GCP implementation is incomplete
--------------------------------------------------------------------------------
/part_2_epic_creation/part_1_create_an_epic.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | from src import create_epic
4 |
5 |
6 | def main():
7 | res = create_epic(
8 | summary="This is a summary",
9 | project="D2",
10 | description="This is a description for an epic",
11 | epic_name="Some Epic Name",
12 | priority="High",
13 | assignee_id='-1')
14 | json_res = json.loads(res.text)
15 | story_key = json_res['key']
16 | print(f"New Epic created - Key: {story_key} ")
17 |
18 |
19 | if __name__ == "__main__":
20 | main()
21 |
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/input/MOCK_DATA_WITH_PROJECT_3_lines.csv:
--------------------------------------------------------------------------------
1 | id,first_name,last_name,email,gender,ip_address,message,project
2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor,D2
3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus,D2
4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui,D3
--------------------------------------------------------------------------------
/part_3_creating_from_csv/README.md:
--------------------------------------------------------------------------------
1 | # JiraScripting - Creating from a CSV
2 |
3 | This section delivers on the promise of creating many Jira issues from a CSV.
4 | CSV's may be hand made and handed over as a work package, be the output of reportng system or given from an external party e.g. an auditor.
5 |
6 | ### What is in this section? ###
7 |
8 | * Create issues from the provided CSV in a single project
9 | * Create issues in specified projects from a provided CSV
10 | * Using the description document generated from https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/ and using variable substitution
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/README.md:
--------------------------------------------------------------------------------
1 | # JiraScripting - Creating Assigning & Emailing
2 |
3 | This section pulls everything together from the earlier sections and shows the practical usecase for maintaining the reporting JSON file outlined in previous sections.
4 |
5 | ### What is in this section? ###
6 |
7 | * Creating and assigning issues and emailing the assignee directly
8 | * Report keeping in the form of a JSON file
9 | * Adding comments on open issues
10 | * Tagging users in comments
11 | * Sending email followups to the assignees of open issues
12 | * Producing an interactive diagram of all issues and their states
--------------------------------------------------------------------------------
/part_0_my_jira_cloud_instance/README.md:
--------------------------------------------------------------------------------
1 | # JiraScripting - My Jira Cloud Instance
2 |
3 | While many Jira cloud instances start off equivalent, over time with user input the extendable nature of Jira Cloud will mean your admin will, at the request of teams using the service, have added many alternatives to the starting set provided out of the box. User beware - these differences may be between projects within the instance also.
4 |
5 | ### What is in this section? ###
6 |
7 | * Get to know your Jira instance - has a basic set of extendable types including issue types, priorities and issue links.
8 | * It is recommended the user add to this as discoveries are made to use as a reference.
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Use this section to tell people about which versions of your project are
6 | currently being supported with security updates.
7 |
8 | | Version | Supported |
9 | | ------- | ------------------ |
10 | | 5.1.x | :white_check_mark: |
11 | | 5.0.x | :x: |
12 | | 4.0.x | :white_check_mark: |
13 | | < 4.0 | :x: |
14 |
15 | ## Reporting a Vulnerability
16 |
17 | Use this section to tell people how to report a vulnerability.
18 |
19 | Tell them where to go, how often they can expect to get an update on a
20 | reported vulnerability, what to expect if the vulnerability is accepted or
21 | declined, etc.
22 |
--------------------------------------------------------------------------------
/just_for_fun/file_access/adding_to_the_mock_data.py:
--------------------------------------------------------------------------------
1 | import csv
2 | from random import randrange
3 |
4 | with open("input/MOCK_DATA.csv") as infile:
5 | reader = csv.reader(infile, delimiter=",")
6 | with open('input/MOCK_DATA.csv', 'r') as csv_input:
7 | with open('output/MOCK_DATA_WITH_PROJECT.csv', 'w') as csv_output:
8 | writer = csv.writer(csv_output, lineterminator='\n')
9 | reader = csv.reader(csv_input)
10 |
11 | new_contents = []
12 | row = next(reader)
13 | row.append('project')
14 | new_contents.append(row)
15 |
16 | for row in reader:
17 | projects = ['D1', 'D2', 'D3']
18 | row.append(projects[randrange(3)])
19 | new_contents.append(row)
20 |
21 | writer.writerows(new_contents)
22 |
--------------------------------------------------------------------------------
/part_1_story_creation/part_1_same_story_for_every_project.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | from src import create_issue
4 | from src import get_all_projects
5 |
6 |
7 | def main():
8 | all_projects = get_all_projects()
9 | for project in all_projects:
10 | project_key = project.get('key', None)
11 | created_issue = create_issue(
12 | summary=f"I am a test in project {project_key}"
13 | , project=project_key
14 | , description="This is a test, please delete me."
15 | , issue_type="Story"
16 | , priority='High'
17 | )
18 |
19 | json_res = json.loads(created_issue.text)
20 | story_key = json_res.get('key', None)
21 | print(f"Newly created Story - Key: {story_key} ")
22 |
23 |
24 | if __name__ == "__main__":
25 | main()
26 |
--------------------------------------------------------------------------------
/src/jirascripting/auth_and_headers.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from dotenv import load_dotenv
3 | import os
4 |
5 | load_dotenv()
6 |
7 |
8 | def jira_auth_and_headers():
9 | """Uses .ENV file variables to authenticate to the Jira API
10 |
11 | Returns:
12 | auth: (HTTPBasicAuth object) for the Jira Cloud instance
13 | headers: (json object) contains required headers for all requests
14 | url: (String) the base URL for the instance
15 |
16 | """
17 | auth = requests.auth.HTTPBasicAuth(os.environ.get("JIRA_EMAIL"), os.environ.get("API_KEY"))
18 |
19 | headers = {
20 | "Accept": "application/json",
21 | "Content-Type": "application/json",
22 | "X-ExperimentalApi": "opt-in"
23 | }
24 |
25 | url = os.environ.get("BASE_URL")
26 |
27 | return auth, headers, url
28 |
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/_follow_up_email_body.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | def email_body(story_key, status, reminders):
4 | body_html = f"""
5 |
6 |
7 |
8 | Hey;
9 |
10 | You have a Jira ticket still in {status}
11 | ❤️❤️I know you are all super busy, but this needs to be done! ❤️❤️
12 | You should have gotten previous reminders
13 |
14 |
15 | {reminders}
16 |
17 |
18 | Here is the Jira story we created for you to report progress - https://YOUR_PROJECT.atlassian.net/browse/{story_key}
19 | Here is the Jira story we created for you to report progress.
20 |
21 | """
22 | return body_html
--------------------------------------------------------------------------------
/just_for_fun/HTML/json2html.html:
--------------------------------------------------------------------------------
1 | Json 2 HTML| glossary | | title | example glossary |
|---|
| GlossDiv | | title | S |
|---|
| GlossList | | GlossEntry | | ID | SGML |
|---|
| SortAs | SGML |
|---|
| GlossTerm | Standard Generalized Markup Language |
|---|
| Acronym | SGML |
|---|
| Abbrev | ISO 8879:1986 |
|---|
| GlossDef | | para | A meta-markup language, used to create markup languages such as DocBook. |
|---|
| GlossSeeAlso | |
|---|
|
|---|
| GlossSee | markup |
|---|
|
|---|
|
|---|
|
|---|
|
|---|
--------------------------------------------------------------------------------
/part_0_my_jira_cloud_instance/get_to_know_your_jira_instance.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | from src import get_issue_types, get_priority_types, get_all_epic_link_types
4 |
5 |
6 | def main():
7 | my_instance = {}
8 | issue_types = get_issue_types()
9 | my_instance['issue_types'] = []
10 | for issue_type in issue_types:
11 | my_instance['issue_types'].append(issue_type.get('name', None))
12 |
13 | priorities = get_priority_types()
14 | my_instance['priorities'] = []
15 | for priority_ in priorities:
16 | my_instance['priorities'].append(priority_.get('name', None))
17 |
18 | issue_links = get_all_epic_link_types()
19 | my_instance['issue_links'] = []
20 | for issue_link in issue_links:
21 | my_instance['issue_links'].append(issue_link.get('name', None))
22 |
23 | return my_instance
24 |
25 |
26 | if __name__ == "__main__":
27 | my_instance_details = main()
28 | with open(f'output/my_instance_details.json', 'w') as outfile:
29 | json.dump(my_instance_details, outfile)
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/input/MOCK_DATA_WITH_PROJECT_6_lines.csv:
--------------------------------------------------------------------------------
1 | id,first_name,last_name,email,gender,ip_address,message,project
2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor,D2
3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus,D2
4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui,D3
5 | 4,Morlee,Summerton,msummerton3@youtube.com,Male,221.95.67.170,quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie,D3
6 | 5,Adler,Steptow,asteptow4@bizjournals.com,Male,215.156.252.103,quis tortor id nulla ultrices aliquet maecenas leo odio condimentum,D3
7 | 6,Susanetta,Peach,speach5@about.com,Female,199.21.109.212,a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue vestibulum,D2
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 David Renton
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/part_1_story_creation/part_2_same_story_for_every_project_assigned_to_a_user.py:
--------------------------------------------------------------------------------
1 | from src import get_all_assignable_users_email
2 | import json
3 |
4 | from src import create_issue
5 | from src import get_all_projects
6 |
7 |
8 | def main():
9 | all_projects = get_all_projects()
10 | assignable_users = get_all_assignable_users_email('D1')
11 | # replace user_email with one you have in your jira instance
12 | user_email = 'davidleerenton@gmail.com'
13 | user_id = assignable_users.get(user_email, None)
14 |
15 | for project in all_projects:
16 | project_key = project.get('key', None)
17 | created_issue = create_issue(
18 | summary=f"I am a test in project {project_key}"
19 | , project=project_key
20 | , description="This is a test, please delete me."
21 | , issue_type="Story"
22 | , assignee_id=user_id
23 | , priority='High'
24 | )
25 |
26 | json_res = json.loads(created_issue.text)
27 | story_key = json_res.get('key', None)
28 | print(f"Newly created Story - Key: {story_key} Assigned to: {user_id} ({user_email})")
29 |
30 |
31 | if __name__ == "__main__":
32 | main()
--------------------------------------------------------------------------------
/part_1_story_creation/part_3_same_story_for_every_project_assigned_to_project_lead.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | from src import create_issue
4 | from src import get_all_projects, get_single_project
5 |
6 |
7 | def main():
8 | all_projects = get_all_projects()
9 |
10 | for project in all_projects:
11 | project_key = project.get('key', None)
12 | project = get_single_project(project_key)
13 | project_lead_id = project.get('lead', {}).get('accountId', "-1")
14 | project_lead_display_name = project.get('lead', {}).get('displayName', "No Name Attached")
15 | created_issue = create_issue(
16 | summary=f"I am a test in project {project_key}"
17 | , project=project_key
18 | , description="This is a test, please delete me."
19 | , issue_type="Story"
20 | , assignee_id=project_lead_id
21 | , priority='High'
22 | )
23 |
24 | json_res = json.loads(created_issue.text)
25 | story_key = json_res.get('key', None)
26 | print(f"Newly created Story - Key: {story_key} Assigned to: {project_lead_id} ({project_lead_display_name})")
27 |
28 |
29 | if __name__ == "__main__":
30 | main()
--------------------------------------------------------------------------------
/part_2_epic_creation/part_2_create_many_linked_epics.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | from src import create_epic
4 | from src import create_epic_link
5 |
6 |
7 | def main():
8 | epic_names = ["Epic one", "Epic two", "Epic three", "Dave", "Other Dave", "Big Dave",
9 | "Tommy Dave", "Jana Dave", "Rich Dave", "Patrick Paterson"]
10 |
11 | uber_epic_creation = create_epic(
12 | summary="This is a summary",
13 | project="D2",
14 | description="This is a description for an uber epic",
15 | epic_name="One Epic to rule them all",
16 | priority="High",
17 | assignee_id='-1')
18 | json_res = json.loads(uber_epic_creation.text)
19 | uber_epic_key = json_res['key']
20 |
21 | for epic_name in epic_names:
22 | epic_creation = create_epic(
23 | summary="This is a summary",
24 | project="D3",
25 | description="This is a description for an uber epic",
26 | epic_name=epic_name,
27 | priority="High",
28 | assignee_id='-1')
29 | json_res = json.loads(epic_creation.text)
30 | epic_key = json_res['key']
31 |
32 | link_response = create_epic_link(epic_key, uber_epic_key, 'Relates')
33 | print(link_response)
34 |
35 |
36 | if __name__ == "__main__":
37 | main()
--------------------------------------------------------------------------------
/part_3_creating_from_csv/part_1_create_from_csv.py:
--------------------------------------------------------------------------------
1 | import csv
2 | import json
3 |
4 | from src import create_issue
5 |
6 |
7 | def main(file_):
8 | with open(file_) as infile:
9 | reader = csv.reader(infile, delimiter=",")
10 | # Skip the header
11 | next(reader, None)
12 | # For each row
13 | for row in reader:
14 | res = create_issue(
15 | summary=f"From CSV - {row[1]} {row[2]}"
16 | , project="D2"
17 | , description=f"""
18 | This could be used to assign people : {row[3]}
19 | Gender : {row[4]}
20 | ip : {row[5]}
21 | Message : {row[6]}"""
22 | , issue_type="Story"
23 | , epic_link="D2-2"
24 | , assignee_id="557058:e747a920-b560-47ee-82e3-94ffe7a59a1b"
25 | , priority='High'
26 | )
27 | if res.status_code == 400:
28 | json_res = json.loads(res.text)
29 | print(json_res['errors'])
30 | else:
31 | json_res = json.loads(res.text)
32 | story_id = json_res['id']
33 | story_key = json_res['key']
34 | print(f"ID: {story_id}, Key: {story_key} ")
35 |
36 |
37 | if __name__ == "__main__":
38 | input_file = "input/MOCK_DATA.csv"
39 | main(input_file)
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/part_5_completeness_percentage_sunburst.py:
--------------------------------------------------------------------------------
1 | import json
2 | import pandas as pd
3 | import plotly.express as px
4 |
5 | filename = 'go_to_devfest'
6 | with open(f'reports/{filename}.json', 'r') as f:
7 | report = json.load(f)
8 |
9 | stories = report['stories']
10 |
11 | df2 = pd.DataFrame.from_dict(stories, orient='index')
12 | # This adds the key in as a column
13 | df2['index'] = df2.index
14 | stories_df = df2.groupby(by=['assignee', 'status_category', 'index']).count()[["hash"]].rename(columns={"hash": "count"})
15 | # This fills each row as the group by gives a hierarchical view
16 | stories_df = stories_df.reset_index()
17 | stories_df.head()
18 | # If you want to see what the dataframe looks like uncomment the print below
19 | # print(stories_df)
20 | fig = px.sunburst(stories_df,
21 | path=['assignee', 'status_category', 'index'],
22 | values='count',
23 | maxdepth=3,
24 | color='status_category',
25 | color_discrete_map={'(?)': 'black', "new": 'red', "indeterminate": 'pink', "done": 'green'}
26 | )
27 | # Open a browser with the interactive graph
28 | fig.show()
29 |
30 | with open(f'reports/{filename}.html', 'a') as f:
31 | f.write(fig.to_html(full_html=False, include_plotlyjs='cdn'))
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/_email_body.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | def email_body(first_name, last_name, gender, ip_address, message, project, story_key):
4 | body_html = f"""
5 |
6 |
7 |
8 | Hey {first_name} {last_name};
9 |
10 | We have created a ticket for your attention in the Jira project {project} as a part of the super important
11 | project
❤️❤️I know you are all super busy, but we need your help! ❤️❤️
12 | {message} needs to be actioned.
13 | This is turning out well.
14 |
15 |
16 | This is some code snippet
17 |
18 |
19 | Add a list if it is needed?
20 |
21 | - Gender: {gender}
22 | - IP Address: {ip_address}
23 | - Project: {project}
24 |
25 | Here is a link to the project confluence page - if there is a chance of questions, start a Confluence page for updates
26 | Here is the Jira story we created for you to report progress - https://YOUR_PROJECT.atlassian.net/browse/{story_key}
27 | Here is the Jira story we created for you to report progress.
28 |
29 | """
30 | return body_html
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/_comment_document.py:
--------------------------------------------------------------------------------
1 | # This file is imported by the part_3_create_in_projects_defined_in_csv.py and part_2_create_fancy_from_csv.py files
2 | # The json object assigned to fancy_description is generated from - https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/
3 |
4 | def comment_doc(id_, reminder, status):
5 | fancy_description = {
6 | "version": 1,
7 | "type": "doc",
8 | "content": [
9 | {
10 | "type": "paragraph",
11 | "content": [
12 | {
13 | "type": "text",
14 | "text": "Hey "
15 | },
16 | {
17 | "type": "mention",
18 | "attrs": {
19 | "id": f"{id_}"
20 | }
21 | },
22 | {
23 | "type": "text",
24 | "text": " have you booked your ticket to DevFest yet?"
25 | }
26 | ]
27 | },
28 | {
29 | "type": "paragraph",
30 | "content": [
31 | {
32 | "type": "text",
33 | "text": f"This ticket was created {reminder}"
34 | }
35 | ]
36 | },
37 | {
38 | "type": "paragraph",
39 | "content": [
40 | {
41 | "type": "text",
42 | "text": f"It’s still in status {status}"
43 | }
44 | ]
45 | }
46 | ]
47 | }
48 | return fancy_description
49 |
--------------------------------------------------------------------------------
/just_for_fun/HTML/json_to_html.py:
--------------------------------------------------------------------------------
1 | from json2html import *
2 | import pdfkit
3 |
4 |
5 | def json_to_html_page(input_):
6 | html_start = '''Json 2 HTML'''
7 | html_end = ''''''
8 | table = json2html.convert(json=input_)
9 | complete_html_page = html_start + table + html_end
10 | return complete_html_page
11 |
12 |
13 | if __name__ == "__main__":
14 | json_input = {
15 | "glossary": {
16 | "title": "example glossary",
17 | "GlossDiv": {
18 | "title": "S",
19 | "GlossList": {
20 | "GlossEntry": {
21 | "ID": "SGML",
22 | "SortAs": "SGML",
23 | "GlossTerm": "Standard Generalized Markup Language",
24 | "Acronym": "SGML",
25 | "Abbrev": "ISO 8879:1986",
26 | "GlossDef": {
27 | "para": "A meta-markup language, used to create markup languages such as DocBook.",
28 | "GlossSeeAlso": ["GML", "XML"]
29 | },
30 | "GlossSee": "markup"
31 | }
32 | }
33 | }
34 | }
35 | }
36 | html_page = json_to_html_page(json_input)
37 | file = open('json2html.html', 'w')
38 | file.write(html_page)
39 | file.close()
40 | pdfkit.from_file('json2html.html', 'json2html2pdf.pdf')
41 |
--------------------------------------------------------------------------------
/emailer/gcp_emailer/gcp_email.py:
--------------------------------------------------------------------------------
1 | import os
2 | from sendgrid import SendGridAPIClient
3 | from sendgrid.helpers.mail import Mail, Email
4 | from python_http_client.exceptions import HTTPError
5 |
6 |
7 | def send_mail(sender: str, recipients: list, title: str, html: str = None) -> dict:
8 | """
9 | Send email to recipients. Sends one mail to all recipients.
10 | To set this up on the GCP console follow this tutorial
11 | https://cloud.google.com/compute/docs/tutorials/sending-mail/using-sendgrid .
12 | """
13 | # If using this module handle the API key with respect
14 | sg = SendGridAPIClient(os.environ['EMAIL_API_KEY'])
15 |
16 | html_content = html
17 |
18 | message = Mail(
19 | to_emails=recipients,
20 | from_email=Email(sender),
21 | subject=title,
22 | html_content=html_content
23 | )
24 |
25 | try:
26 | response = sg.send(message)
27 | return_message = f"email.status_code={response.status_code}"
28 | #expected 202 Accepted
29 |
30 | except HTTPError as e:
31 | return_message = e.message
32 |
33 | return return_message
34 |
35 |
36 | if __name__ == '__main__':
37 | # replace sender_ with the email address you registered in AWS SES
38 | sender_ = 'david.renton@genesys.com'
39 | recipients_ = ['davidleerenton@gmail.com']
40 | title_ = 'DevFest'
41 | text_ = 'DevFest is awesome'
42 | body_ = """A header 1
Some text."""
43 |
44 | response_ = send_mail(sender_, recipients_, title_, text_, body_)
45 | print(response_)
--------------------------------------------------------------------------------
/part_1_story_creation/part_4_same_story_for_every_project_assigned_with_report.py:
--------------------------------------------------------------------------------
1 | from src import get_all_assignable_users_email
2 | import json
3 |
4 | from src import create_issue
5 | from just_for_fun.HTML.json_to_html import json_to_html_page
6 | from src import get_all_projects
7 |
8 |
9 | def main():
10 | all_projects = get_all_projects()
11 | assignable_users = get_all_assignable_users_email('D1')
12 | campaign_report_ = {}
13 | project_keys = []
14 |
15 | for project in all_projects:
16 | project_keys.append(project.get('key', None))
17 |
18 | for project_key in project_keys:
19 | if project_key is not None:
20 | created_issue = create_issue(
21 | summary=f"I am a test in project {project_key}"
22 | , project=project_key
23 | , description="This is a test, please delete me."
24 | , issue_type="Story"
25 | # replace the email below with one from your jira project
26 | , assignee_id=assignable_users.get('davidleerenton@gmail.com', None)
27 | , priority='High'
28 | )
29 |
30 | json_res = json.loads(created_issue.text)
31 | story_key = json_res.get('key', None)
32 | campaign_report_[f'{project_key}'] = {}
33 | campaign_report_[f'{project_key}']['created_story'] = story_key
34 | return campaign_report_
35 |
36 |
37 | if __name__ == "__main__":
38 | campaign_report = main()
39 | campaign_name = "my_super_report"
40 | with open(f'reports/{campaign_name}_report.json', 'w') as outfile:
41 | json.dump(campaign_report, outfile)
42 |
43 | html_page = json_to_html_page(campaign_report)
44 | file = open(f'reports/{campaign_name}_report.html', 'w')
45 | file.write(html_page)
46 | file.close()
47 |
48 |
49 |
--------------------------------------------------------------------------------
/part_2_epic_creation/part_3_create_many_linked_epics_with_record.py:
--------------------------------------------------------------------------------
1 | import atexit
2 | import json
3 |
4 | from src import create_epic
5 | from src import create_epic_link
6 | from just_for_fun.HTML.json_to_html import json_to_html_page
7 |
8 | campaign_report = {}
9 |
10 |
11 | def main():
12 | epic_names = ["Epic one", "Epic two", "Epic three"]
13 |
14 | uber_epic_creation = create_epic(
15 | summary="This is a summary",
16 | project="D2",
17 | description="This is a description for an uber epic",
18 | epic_name="One Epic to rule them all",
19 | priority="High",
20 | assignee_id='-1')
21 | json_res = json.loads(uber_epic_creation.text)
22 | uber_epic_key = json_res['key']
23 | campaign_report['uber_epic'] = {f'{uber_epic_key}': {}}
24 | campaign_report[f'epics'] = {}
25 |
26 | for epic_name in epic_names:
27 | epic_creation = create_epic(
28 | summary="This is a summary",
29 | project="D3",
30 | description="This is a description for an uber epic",
31 | epic_name=epic_name,
32 | priority="High",
33 | assignee_id='-1')
34 | json_res = json.loads(epic_creation.text)
35 | epic_key = json_res['key']
36 | campaign_report['epics'][f'{epic_key}'] = {}
37 |
38 | link_response = create_epic_link(epic_key, uber_epic_key, 'Relates')
39 | print(link_response)
40 |
41 |
42 | @atexit.register
43 | def final_function():
44 | campaign_name = "my_super_at_exit"
45 | with open(f'reports/{campaign_name}_report.json', 'w') as outfile:
46 | json.dump(campaign_report, outfile)
47 |
48 | html_page = json_to_html_page(campaign_report)
49 | file = open(f'reports/{campaign_name}_report.html', 'w')
50 | file.write(html_page)
51 | file.close()
52 |
53 |
54 | if __name__ == "__main__":
55 | main()
56 |
--------------------------------------------------------------------------------
/part_3_creating_from_csv/part_2_create_fancy_from_csv.py:
--------------------------------------------------------------------------------
1 | import csv
2 | import json
3 |
4 | from src import get_all_assignable_users_email
5 | from src import create_fancy_issue
6 | from part_3_creating_from_csv._description_document import description_doc
7 |
8 | assignable_users = get_all_assignable_users_email('D1')
9 |
10 |
11 | def main(file_):
12 | with open(file_) as infile:
13 | reader = csv.reader(infile, delimiter=",")
14 | # Skip the header
15 | next(reader, None)
16 | # For each row
17 | for row in reader:
18 | # get user id from email, this could be provided in th csv file
19 | # replace the below email with one from your jira instance
20 | assignable_user_email = 'davidleerenton@gmail.com'
21 | assignable_user_id = assignable_users.get(assignable_user_email, None)
22 |
23 | first_name = row[1]
24 | last_name = row[2]
25 | email = row[3]
26 | gender = row[4]
27 | ip_address = row[5]
28 | message = row[6]
29 | # Create the description document
30 | description_document = description_doc(first_name, last_name, email, gender, ip_address, message)
31 | res = create_fancy_issue(
32 | summary=f"From CSV - {first_name} {last_name}"
33 | , project="D2"
34 | , description_doc=description_document
35 | , issue_type="Story"
36 | , epic_link="D2-2"
37 | , assignee_id=assignable_user_id
38 | , priority='High'
39 | )
40 | if res.status_code == 400:
41 | json_res = json.loads(res.text)
42 | print(json_res['errors'])
43 | else:
44 | json_res = json.loads(res.text)
45 | story_id = json_res['id']
46 | story_key = json_res['key']
47 | print(f"ID: {story_id}, Key: {story_key} ")
48 |
49 |
50 | if __name__ == "__main__":
51 | input_file = "input/MOCK_DATA.csv"
52 | main(input_file)
53 |
--------------------------------------------------------------------------------
/part_3_creating_from_csv/part_3_create_in_projects_defined_in_csv.py:
--------------------------------------------------------------------------------
1 | import csv
2 | import json
3 |
4 | from src import get_all_assignable_users_email
5 | from src import create_fancy_issue
6 | from part_3_creating_from_csv._description_document import description_doc
7 |
8 | assignable_users = get_all_assignable_users_email('D1')
9 |
10 |
11 | def main(file_):
12 | with open(file_) as infile:
13 | reader = csv.reader(infile, delimiter=",")
14 | # Skip the header
15 | next(reader, None)
16 | # For each row
17 | for row in reader:
18 | # get user id from email, this could be provided in th csv file
19 | # replace the below email with one from your jira instance
20 | assignable_user_email = 'davidleerenton@gmail.com'
21 | assignable_user_id = assignable_users.get(assignable_user_email, None)
22 |
23 | first_name = row[1]
24 | last_name = row[2]
25 | email = row[3]
26 | gender = row[4]
27 | ip_address = row[5]
28 | message = row[6]
29 | project = row[7]
30 | # Create the description document
31 | description_document = description_doc(first_name, last_name, email, gender, ip_address, message)
32 | res = create_fancy_issue(
33 | summary=f"From CSV - {first_name} {last_name}"
34 | , project=project
35 | , description_doc=description_document
36 | , issue_type="Story"
37 | , epic_link="D2-2"
38 | , assignee_id=assignable_user_id
39 | , priority='High'
40 | )
41 | if res.status_code == 400:
42 | json_res = json.loads(res.text)
43 | print(json_res['errors'])
44 | else:
45 | json_res = json.loads(res.text)
46 | story_id = json_res['id']
47 | story_key = json_res['key']
48 | print(f"ID: {story_id}, Key: {story_key} ")
49 |
50 |
51 | if __name__ == "__main__":
52 | input_file = "input/MOCK_DATA_WITH_PROJECT.csv"
53 | main(input_file)
54 |
--------------------------------------------------------------------------------
/just_for_fun/qr_code/qr_code_production.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | import qrcode
4 | from qrcode.image.styledpil import StyledPilImage
5 | from qrcode.image.styles.moduledrawers import RoundedModuleDrawer
6 | from qrcode.image.styles.colormasks import RadialGradiantColorMask
7 |
8 |
9 | def make_qr_code(url):
10 | qr = qrcode.QRCode(version=1, box_size=5, border=5)
11 | qr.add_data(url)
12 | qr.make()
13 |
14 | img = qr.make_image(fill_color='black', back_color='white')
15 | return img
16 |
17 |
18 | def make_qr_with_image_code(url, image):
19 | qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_H)
20 | qr.add_data(url)
21 | img = qr.make_image(image_factory=StyledPilImage, embeded_image_path=image)
22 | return img
23 |
24 |
25 | def make_qr_with_colour_mask_code(url):
26 | qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_H)
27 | qr.add_data(url)
28 | img = qr.make_image(image_factory=StyledPilImage, color_mask=RadialGradiantColorMask())
29 | return img
30 |
31 |
32 | def make_rounded_qr_code(url):
33 | qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_H)
34 | qr.add_data(url)
35 | img = qr.make_image(image_factory=StyledPilImage, module_drawer=RoundedModuleDrawer())
36 | return img
37 |
38 |
39 | if __name__ == "__main__":
40 | website_link = 'https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/'
41 | my_path = "qr_codes"
42 | image_path = "images/Genesys_square_logo.png"
43 | name_ = "genesys_request"
44 |
45 | file_name = f"{name_}_standard.png"
46 | saved_path = os.path.join(my_path, file_name)
47 | qr_code = make_qr_code(website_link)
48 | qr_code.save(saved_path)
49 |
50 | file_name = f"{name_}_with_image.png"
51 | saved_path = os.path.join(my_path, file_name)
52 | qr_code = make_qr_with_image_code(website_link, image_path)
53 | qr_code.save(saved_path)
54 |
55 | file_name = f"{name_}_with_mask.png"
56 | saved_path = os.path.join(my_path, file_name)
57 | qr_code = make_qr_with_colour_mask_code(website_link)
58 | qr_code.save(saved_path)
59 |
60 | file_name = f"{name_}_rounded.png"
61 | saved_path = os.path.join(my_path, file_name)
62 | qr_code = make_rounded_qr_code(website_link)
63 | qr_code.save(saved_path)
64 |
65 |
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/part_3_follow_up_with_a_comment.py:
--------------------------------------------------------------------------------
1 | import json
2 | from datetime import datetime
3 |
4 | from src import get_issue_status, get_issue_status_category, add_fancy_comment_to_story, get_issue_assignee
5 | from part_4_creating_assigning_and_emailing._comment_document import comment_doc
6 |
7 |
8 | def main(initiative_name_):
9 | date_ = datetime.now()
10 | f_name = f"reports/{initiative_name_}.json"
11 | with open(f'{f_name}', 'r+') as initiative_:
12 | init_ = json.load(initiative_)
13 |
14 | for story in init_["stories"]:
15 | if init_["stories"][f"{story}"]["status_category"] != "done":
16 | story_status_category = get_issue_status_category(story)
17 | if story_status_category == "done":
18 | init_["stories"][f"{story}"]["status_category"] = story_status_category
19 | continue
20 | else:
21 | story_status = get_issue_status(story)
22 | this_assignee = get_issue_assignee(story)
23 | if this_assignee["assignee_id"] != init_["stories"][f"{story}"]["assignee_id"]:
24 | init_["stories"][f"{story}"]["assignee_id"] = this_assignee["assignee_id"]
25 | init_["stories"][f"{story}"]["assignee"] = this_assignee["assignee_email"]
26 | comment_document = comment_doc(init_["stories"][f"{story}"]["assignee_id"],
27 | init_["stories"][f"{story}"]["reminder"],
28 | story_status)
29 | try:
30 | comment = add_fancy_comment_to_story(story, comment_document)
31 | init_['stories'][f'{story}']['reminder'].append(
32 | f"Reminder comment was added on {date_}")
33 | except:
34 | with open(f'reports/{initiative_name_}.json', 'w') as outfile:
35 | json.dump(init_, outfile)
36 | with open(f'reports/{initiative_name_}.json', 'w') as outfile:
37 | json.dump(init_, outfile)
38 |
39 |
40 | if __name__ == "__main__":
41 | initiative_name = "go_to_devfest"
42 | main(initiative_name)
43 |
44 | with open(f'reports/{initiative_name}.json', 'r+') as initiative:
45 | init = json.load(initiative)
46 | print(json.dumps(init, indent=4))
47 |
--------------------------------------------------------------------------------
/src/jirascripting/create_jira_epic.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import json
3 | from src import jira_auth_and_headers
4 |
5 |
6 | def create_epic(summary, project, description, epic_name, priority, assignee_id="-1"):
7 | """Creates an epic
8 |
9 | Parameters:
10 | summary (string): The issue summary
11 | project (string): What Jira project should this be in SECCOMPPM is 21697
12 | description (string): The issue description
13 | epic_name (string): The name of this epic
14 | priority (string): Text Highest, High, Medium, Low, Lowest
15 | assignee_id (string): The ID of the assignable user.
16 |
17 | Returns:
18 | response object: this will have the response code and in the text will have the details of the created epic
19 |
20 | """
21 | auth, headers, base_url = jira_auth_and_headers()
22 | # create issue
23 | url = f"{base_url}/rest/api/3/issue"
24 |
25 | # create content
26 | content_list = []
27 | paragraph_content = []
28 | content_obj = {}
29 | content = {'text': description, 'type': "text"}
30 | content_obj['type'] = "paragraph"
31 | paragraph_content.append(content)
32 | content_obj['content'] = paragraph_content
33 |
34 | # create issue
35 | issue = {'fields': {}}
36 | issue['fields']['summary'] = summary
37 | issue['fields']['issuetype'] = {'name': 'Epic'}
38 | issue['fields']['project'] = {'key': project}
39 | content_list.append(content_obj)
40 | issue['fields']['description'] = {'type': "doc", 'version': 1, 'content': content_list}
41 | issue['fields']['priority'] = {'name': priority}
42 | issue['fields']['assignee'] = {'id': assignee_id}
43 | issue['fields']['customfield_10011'] = f"{epic_name}"
44 |
45 | payload = json.dumps(issue)
46 |
47 | response = requests.request(
48 | "POST",
49 | url,
50 | data=payload,
51 | headers=headers,
52 | auth=auth
53 | )
54 | return response
55 |
56 |
57 | if __name__ == "__main__":
58 | res = create_epic(
59 | summary="This is a summary",
60 | project="D2",
61 | description="This is a description for an epic",
62 | epic_name="Some Epic Name",
63 | priority="High")
64 | json_res = json.loads(res.text)
65 | story_id = json_res['id']
66 | story_key = json_res['key']
67 | print(f"ID: {story_id}, Key: {story_key} ")
68 |
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/part_4_follow_up_with_an_email.py:
--------------------------------------------------------------------------------
1 | import json
2 | from datetime import datetime
3 |
4 | from src import get_issue_status, get_issue_status_category, get_issue_assignee
5 | from part_4_creating_assigning_and_emailing._follow_up_email_body import email_body
6 | from emailer.aws_emailer.email_with_attachment import send_mail
7 |
8 |
9 | def main(initiative_name_):
10 | date_ = datetime.now()
11 | f_name = f"reports/{initiative_name_}.json"
12 | with open(f'{f_name}', 'r+') as initiative_:
13 | init_ = json.load(initiative_)
14 |
15 | for story in init_["stories"]:
16 | if init_["stories"][f"{story}"]["status_category"] != "done":
17 | story_status_category = get_issue_status_category(story)
18 | if story_status_category == "done":
19 | init_["stories"][f"{story}"]["status_category"] = story_status_category
20 | continue
21 | else:
22 | story_status = get_issue_status(story)
23 | this_assignee = get_issue_assignee(story)
24 | if this_assignee["assignee_id"] != init_["stories"][f"{story}"]["assignee_id"]:
25 | init_["stories"][f"{story}"]["assignee_id"] = this_assignee["assignee_id"]
26 | init_["stories"][f"{story}"]["assignee"] = this_assignee["assignee_email"]
27 |
28 | sender_ = 'david.renton@genesys.com'
29 | recipients_ = [f'{init_["stories"][f"{story}"]["assignee"]}']
30 | cc_ = ['davidleerenton@gmail.com', 'hello@devfestireland.com']
31 | title_ = 'DevFest Ireland'
32 | text_ = 'REMINDER - DevFest is awesome'
33 | body_ = email_body(story, story_status, init_["stories"][f"{story}"]["reminder"])
34 | attachments_ = ['input/devfestireland_with_image.png']
35 | try:
36 | response_ = send_mail(sender_, recipients_, cc_, title_, text_, body_, attachments_)
37 | print(response_)
38 | init_['stories'][f'{story}']['reminder'].append(
39 | f"Reminder email with subject {title_} was sent to {recipients_} on {date_}")
40 | except:
41 | with open(f'reports/{initiative_name_}.json', 'w') as outfile:
42 | json.dump(init_, outfile)
43 | with open(f'reports/{initiative_name_}.json', 'w') as outfile:
44 | json.dump(init_, outfile)
45 |
46 |
47 | if __name__ == "__main__":
48 | initiative_name = "go_to_devfest"
49 | main(initiative_name)
50 |
51 | with open(f'reports/{initiative_name}.json', 'r+') as initiative:
52 | init = json.load(initiative)
53 | print(json.dumps(init, indent=4))
54 |
--------------------------------------------------------------------------------
/src/jirascripting/get_assignable_users.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from src.jirascripting.auth_and_headers import jira_auth_and_headers
3 | import json
4 |
5 |
6 | def _get_assignable_users(key, start_from):
7 | auth, headers, base_url = jira_auth_and_headers()
8 | url = f"{base_url}/rest/api/3/user/assignable/search"
9 |
10 | query = {
11 | 'project': key,
12 | 'startAt': start_from
13 | }
14 |
15 | response = requests.request(
16 | "GET",
17 | url,
18 | headers=headers,
19 | params=query,
20 | auth=auth
21 | )
22 | return response
23 |
24 |
25 | def get_all_assignable_users_name(project_key):
26 | """Returns a Json object with usernames mapped to logical ID
27 | Parameters:
28 | project_key (string): The key of an active project in the target Jira instance.
29 | Returns:
30 | response object: Json object with available users in the targeted Jira instance with their logical ID's.
31 | """
32 | start_at = 0
33 | my_json = {}
34 | while start_at is not None:
35 | user_list_response = _get_assignable_users(project_key, start_at)
36 | text_contents = json.loads(user_list_response.text)
37 | for user in text_contents:
38 | my_json[f"{user.get('displayName', None)}"] = user.get('accountId', None)
39 | if len(text_contents) == 100:
40 | start_at = start_at + 100
41 | else:
42 | start_at = None
43 |
44 | return my_json
45 |
46 |
47 | def get_all_assignable_users_email(project_key):
48 | """Returns a Json object with email mapped to logical ID
49 | Parameters:
50 | project_key (string): The key of an active project in the target Jira instance.
51 | Returns:
52 | response object: Json object with available users in the targeted Jira instance with their logical ID's.
53 | """
54 | start_at = 0
55 | my_json = {}
56 | while start_at is not None:
57 | user_list_response = _get_assignable_users(project_key, start_at)
58 | text_contents = json.loads(user_list_response.text)
59 | for user in text_contents:
60 | my_json[f"{user.get('emailAddress', None)}"] = user.get('accountId', None)
61 | if len(text_contents) == 100:
62 | start_at = start_at + 100
63 | else:
64 | start_at = None
65 |
66 | return my_json
67 |
68 |
69 | if __name__ == "__main__":
70 | jira_project_key = 'D1'
71 | returned_json_name = get_all_assignable_users_name(jira_project_key)
72 | print(json.dumps(returned_json_name, indent=4))
73 |
74 | returned_json_email = get_all_assignable_users_email(jira_project_key)
75 | print(json.dumps(returned_json_email, indent=4))
--------------------------------------------------------------------------------
/src/jirascripting/create_jira_issue.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import json
3 | from src import jira_auth_and_headers
4 |
5 |
6 | def create_issue(summary, project, description, epic_link=None, assignee_id=None, priority="High", issue_type="Story"):
7 | """Creates a story under an epic
8 |
9 | Parameters:
10 | summary (string): The issue summary.
11 | project (string): Project key eg. SECCOMPPM.
12 | description (string): The issue description.
13 | epic_link (string): The epic identifier eg: SECCOMPPM-93.
14 | assignee_id (string): The ID of the assignable user.
15 | issue_type (string): Text description of what entity you wish to create eg, Story, Bug, Task
16 | priority(string): Text Highest, High, Medium, Low, Lowest
17 |
18 | Returns:
19 | response object: This will have the response code and in the text will have the details of the created issue.
20 |
21 | """
22 | auth, headers, base_url = jira_auth_and_headers()
23 | # create content
24 | content_list = []
25 | paragraph_content = []
26 | content_obj = {}
27 | content = {'text': description, 'type': "text"}
28 | content_obj['type'] = "paragraph"
29 | paragraph_content.append(content)
30 | content_obj['content'] = paragraph_content
31 |
32 | # create issue
33 | issue = {'fields': {}}
34 | issue['fields']['summary'] = summary
35 | issue['fields']['issuetype'] = {'name': issue_type}
36 | issue['fields']['project'] = {'key': project}
37 | content_list.append(content_obj)
38 | issue['fields']['description'] = {'type': "doc", 'version': 1, 'content': content_list}
39 | issue['fields']['priority'] = {'name': priority}
40 | if assignee_id is not None:
41 | issue['fields']['assignee'] = {'id': assignee_id}
42 | else:
43 | issue['fields']['assignee'] = {'id': "-1"}
44 | if epic_link is not None:
45 | issue['fields']['parent'] = {'key': epic_link}
46 |
47 | url = f"{base_url}/rest/api/3/issue"
48 |
49 | payload = json.dumps(issue)
50 |
51 | response = requests.request(
52 | "POST",
53 | url,
54 | data=payload,
55 | headers=headers,
56 | auth=auth
57 | )
58 | return response
59 |
60 |
61 | if __name__ == "__main__":
62 | res = create_issue(
63 | summary="Delete Me"
64 | , project="D1"
65 | , description="This is a test, please delete me."
66 | , issue_type="Story"
67 | # , epic_link="D1-6"
68 | , assignee_id="557058:e747a920-b560-47ee-82e3-94ffe7a59a1b"
69 | , priority='High'
70 | )
71 | if res.status_code == 400:
72 | json_res = json.loads(res.text)
73 | print(json_res['errors'])
74 | else:
75 | json_res = json.loads(res.text)
76 | story_id = json_res['id']
77 | story_key = json_res['key']
78 | print(f"ID: {story_id}, Key: {story_key} ")
--------------------------------------------------------------------------------
/src/jirascripting/create_jira_issue_with_parent.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import json
3 | from src.jirascripting.auth_and_headers import jira_auth_and_headers
4 |
5 |
6 | def create_issue_parent(summary, project, description, assignee_id=None, priority="High", issue_type="Story", parent=None):
7 | """
8 | Creates a story under an epic
9 |
10 | Parameters:
11 | parent (string): The key of the parent epic
12 | summary (string): The issue summary.
13 | project (string): Project key.
14 | description (string): The issue description.
15 | assignee_id (string): The ID of the assignable user.
16 | issue_type (string): Text description of what entity you wish to create eg, Story, Bug, Task
17 | priority(string): Text Highest, High, Medium, Low, Lowest
18 |
19 | Returns:
20 | response object: This will have the response code and in the text will have the details of the created issue.
21 |
22 | """
23 |
24 | auth, headers, base_url = jira_auth_and_headers()
25 | # create content
26 | content_list = []
27 | paragraph_content = []
28 | content_obj = {}
29 | content = {'text': description, 'type': "text"}
30 | content_obj['type'] = "paragraph"
31 | paragraph_content.append(content)
32 | content_obj['content'] = paragraph_content
33 |
34 | # create issue
35 | issue = {'fields': {}}
36 | issue['fields']['summary'] = summary
37 | if parent is not None:
38 | issue['fields']['parent'] = {'key': parent}
39 | issue['fields']['issuetype'] = {'name': issue_type}
40 | issue['fields']['project'] = {'key': project}
41 | content_list.append(content_obj)
42 | issue['fields']['description'] = {'type': "doc", 'version': 1, 'content': content_list}
43 | issue['fields']['priority'] = {'name': priority}
44 | if assignee_id is not None:
45 | issue['fields']['assignee'] = {'id': assignee_id}
46 | else:
47 | issue['fields']['assignee'] = {'id': "-1"}
48 |
49 | url = f"{base_url}/rest/api/3/issue"
50 |
51 | payload = json.dumps(issue)
52 |
53 | response = requests.request(
54 | "POST",
55 | url,
56 | data=payload,
57 | headers=headers,
58 | auth=auth
59 | )
60 | return response
61 |
62 |
63 | if __name__ == "__main__":
64 | res = create_issue_parent(
65 | summary="Parent test"
66 | , project="D1"
67 | , description="Parent test."
68 | , issue_type="Story"
69 | # , epic_link="D1-6"
70 | , assignee_id="557058:e747a920-b560-47ee-82e3-94ffe7a59a1b"
71 | , priority='High'
72 | , parent='D1-7'
73 | )
74 | if res.status_code == 400:
75 | json_res = json.loads(res.text)
76 | print(json_res['errors'])
77 | else:
78 | json_res = json.loads(res.text)
79 | story_id = json_res['id']
80 | story_key = json_res['key']
81 | print(f"ID: {story_id}, Key: {story_key} ")
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/part_1_create_assign_email.py:
--------------------------------------------------------------------------------
1 | import csv
2 | import json
3 |
4 | from src import get_all_assignable_users_email
5 | from src import create_fancy_issue
6 | from emailer.aws_emailer.email_with_attachment import send_mail
7 | from part_4_creating_assigning_and_emailing._description_document import description_doc
8 | from part_4_creating_assigning_and_emailing._email_body import email_body
9 |
10 | assignable_users = get_all_assignable_users_email('D1')
11 |
12 |
13 | def main(file_):
14 | with open(file_) as infile:
15 | reader = csv.reader(infile, delimiter=",")
16 | # Skip the header
17 | next(reader, None)
18 | # For each row
19 | for row in reader:
20 | # get user id from email, this could be provided in th csv file
21 | # replace the below email with one from your jira instance
22 | assignable_user_email = 'davidleerenton@gmail.com'
23 | assignable_user_id = assignable_users.get(assignable_user_email, None)
24 | # these don't need to be assigned, this way just makes it more readable when debugging.
25 | first_name = row[1]
26 | last_name = row[2]
27 | email = row[3]
28 | gender = row[4]
29 | ip_address = row[5]
30 | message = row[6]
31 | project = row[7]
32 | # Create the description document
33 | description_document = description_doc(first_name, last_name, email, gender, ip_address, message)
34 | # Build and execute the call to the Jira Cloud API
35 | res = create_fancy_issue(
36 | summary=f"From CSV - {first_name} {last_name}"
37 | , project=project
38 | , description_doc=description_document
39 | , issue_type="Story"
40 | , epic_link="D2-2"
41 | , assignee_id=assignable_user_id
42 | , priority='High'
43 | )
44 | if res.status_code == 400:
45 | json_res = json.loads(res.text)
46 | print(json_res['errors'])
47 | else:
48 | json_res = json.loads(res.text)
49 | story_key = json_res['key']
50 | print(f"Story created - Key: {story_key} ")
51 |
52 | # replace the sender_ email with the one registered in AWS SES
53 | sender_ = 'david.renton@genesys.com'
54 | recipients_ = [f'{assignable_user_email}']
55 | cc_ = ['davidleerenton@gmail.com', 'hello@devfestireland.com']
56 | title_ = 'DevFest Ireland'
57 | text_ = 'DevFest is awesome'
58 | body_ = email_body(first_name, last_name, gender, ip_address, message, project, story_key)
59 | attachments_ = ['input/devfestireland_with_image.png']
60 |
61 | response_ = send_mail(sender_, recipients_, cc_, title_, text_, body_, attachments_)
62 | print(response_)
63 |
64 |
65 | if __name__ == "__main__":
66 | input_file = "input/MOCK_DATA_WITH_PROJECT.csv"
67 | main(input_file)
68 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ "main" ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ "main" ]
20 | schedule:
21 | - cron: '40 9 * * 3'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'python' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Use only 'java' to analyze code written in Java, Kotlin or both
38 | # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
39 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
40 |
41 | steps:
42 | - name: Checkout repository
43 | uses: actions/checkout@v3
44 |
45 | # Initializes the CodeQL tools for scanning.
46 | - name: Initialize CodeQL
47 | uses: github/codeql-action/init@v2
48 | with:
49 | languages: ${{ matrix.language }}
50 | # If you wish to specify custom queries, you can do so here or in a config file.
51 | # By default, queries listed here will override any specified in a config file.
52 | # Prefix the list here with "+" to use these queries and those in the config file.
53 |
54 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
55 | # queries: security-extended,security-and-quality
56 |
57 |
58 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
59 | # If this step fails, then you should remove it and run the build manually (see below)
60 | - name: Autobuild
61 | uses: github/codeql-action/autobuild@v2
62 |
63 | # ℹ️ Command-line programs to run using the OS shell.
64 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
65 |
66 | # If the Autobuild fails above, remove it and uncomment the following three lines.
67 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
68 |
69 | # - run: |
70 | # echo "Run, Build Application using script"
71 | # ./location_of_script_within_repo/buildscript.sh
72 |
73 | - name: Perform CodeQL Analysis
74 | uses: github/codeql-action/analyze@v2
75 | with:
76 | category: "/language:${{matrix.language}}"
77 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .idea/*
106 | .env
107 | .venv
108 | env/
109 | venv/
110 | ENV/
111 | env.bak/
112 | venv.bak/
113 |
114 | # Spyder project settings
115 | .spyderproject
116 | .spyproject
117 |
118 | # Rope project settings
119 | .ropeproject
120 |
121 | # mkdocs documentation
122 | /site
123 |
124 | # mypy
125 | .mypy_cache/
126 | .dmypy.json
127 | dmypy.json
128 |
129 | # Pyre type checker
130 | .pyre/
131 |
132 | # project speciffic
133 | .env
134 | .idea
135 | .idea/*
136 |
137 | just_for_fun/images.*
138 | !just_for_fun/qr_code/images/.gitkeep
139 |
140 | just_for_fun/qr_codes.*
141 | !just_for_fun/qr_code/qr_codes/.gitkeep
142 |
143 | part_1_story_creation/reports/*
144 | !part_1_story_creation/reports/.gitkeep
145 |
146 | part_2_epic_creation/reports/*
147 | !part_2_epic_creation/reports/.gitkeep
148 |
149 | part_3_creating_from_csv/input/*
150 | !part_3_creating_from_csv/input/.gitkeep
151 | !part_3_creating_from_csv/input/MOCK_DATA.csv
152 | !part_3_creating_from_csv/input/MOCK_DATA_WITH_PROJECT.csv
153 |
154 | part_4_creating_assigning_and_emailing/input*
155 | !part_4_creating_assigning_and_emailing/input/.gitkeep
156 | !part_4_creating_assigning_and_emailing/input/MOCK_DATA_WITH_PROJECT.csv
157 | !part_4_creating_assigning_and_emailing/input/MOCK_DATA_WITH_PROJECT_3_lines.csv
158 | !part_4_creating_assigning_and_emailing/input/MOCK_DATA_WITH_PROJECT_6_lines.csv
159 |
160 | part_4_creating_assigning_and_emailing/reports/*
161 | !part_4_creating_assigning_and_emailing/reports/.gitkeep
162 |
163 |
164 | part_0_my_jira_cloud_instance/output/*
165 | !part_0_my_jira_cloud_instance/output/.gitkeep
166 |
167 |
--------------------------------------------------------------------------------
/emailer/aws_emailer/email_with_attachment.py:
--------------------------------------------------------------------------------
1 | import os
2 | import boto3
3 | from email.mime.multipart import MIMEMultipart
4 | from email.mime.text import MIMEText
5 | from email.mime.application import MIMEApplication
6 |
7 |
8 | def create_multipart_message(
9 | sender: str, recipients: list, cc: list, title: str, text: str = None, html: str = None, attachments: list = None) \
10 | -> MIMEMultipart:
11 | """
12 | Creates a MIME multipart message object.
13 | Uses only the Python `email` standard library.
14 | Emails, both sender and recipients, can be just the email string or have the format 'The Name '.
15 |
16 | :param sender: The sender.
17 | :param recipients: List of recipients. Needs to be a list, even if only one recipient.
18 | :param title: The title of the email.
19 | :param text: The text version of the email body (optional).
20 | :param html: The html version of the email body (optional).
21 | :param attachments: List of files to attach in the email.
22 | :return: A `MIMEMultipart` to be used to send the email.
23 | """
24 | multipart_content_subtype = 'alternative' if text and html else 'mixed'
25 | msg = MIMEMultipart(multipart_content_subtype)
26 | msg['Subject'] = title
27 | msg['From'] = sender
28 | msg['To'] = ', '.join(recipients)
29 | msg['Cc'] = ', '.join(cc)
30 |
31 | # Record the MIME types of both parts - text/plain and text/html.
32 | # According to RFC 2046, the last part of a multipart message, in this case the HTML message, is best and preferred.
33 | if text:
34 | part = MIMEText(text, 'plain')
35 | msg.attach(part)
36 | if html:
37 | part = MIMEText(html, 'html')
38 | msg.attach(part)
39 |
40 | # Add attachments
41 | for attachment in attachments or []:
42 | with open(attachment, 'rb') as f:
43 | part = MIMEApplication(f.read())
44 | part.add_header('Content-Disposition', 'attachment', filename=os.path.basename(attachment))
45 | msg.attach(part)
46 |
47 | return msg
48 |
49 |
50 | def send_mail(
51 | sender: str, recipients: list, cc: list, title: str, text: str = None, html: str = None,
52 | attachments: list = None) -> dict:
53 | """
54 | Send email to recipients. Sends one mail to all recipients.
55 | The sender needs to be a verified email in SES.
56 | """
57 | msg = create_multipart_message(sender, recipients, cc, title, text, html, attachments)
58 | ses_client = boto3.client('ses') # Use your settings here
59 |
60 | # If you are using this in a personal capacity and want to add credentials directly use the method below
61 | # ses_client = boto3.client('ses',
62 | # aws_access_key_id=settings.AWS_SERVER_PUBLIC_KEY,
63 | # aws_secret_access_key=settings.AWS_SERVER_SECRET_KEY,
64 | # region_name=REGION_NAME
65 | # )
66 | final_destinations = recipients + cc
67 | return ses_client.send_raw_email(
68 | Source=sender,
69 | Destinations=final_destinations,
70 | RawMessage={'Data': msg.as_string()}
71 | )
72 |
73 |
74 | if __name__ == '__main__':
75 | # replace sender_ with the email address you registered in AWS SES
76 | sender_ = 'david.renton@genesys.com'
77 | recipients_ = ['devfestireland@gmail.com']
78 | cc_ = ['davidleerenton@gmail.com', 'hello@devfestireland.com']
79 | title_ = 'DevFest'
80 | text_ = 'DevFest is awesome'
81 | body_ = """A header 1
Some text."""
82 | attachments_ = ['../../just_for_fun/qr_code/qr_codes/with_image.png']
83 |
84 | response_ = send_mail(sender_, recipients_, cc_, title_, text_, body_, attachments_)
85 | print(response_)
86 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JiraScripting
2 |
3 | This repo is being made available as is, minimal tidy-up has been done, I will continue to support and refactor as time allows (pull requests welcome).
4 |
5 | This is code I have used to create hundreds of Jira tickets in minutes saving hours/days of Jira Donkey work.
6 |
7 | Refactors, updates, additions and new ways of using this would be greatly appreciated, please consider contributing.
8 |
9 | ## What is this repository for? ##
10 |
11 | * Quick summary:
12 | * Automating Jira Epic & Story creation
13 | * Commenting on issues
14 | * Emailing assignees
15 | * Tracking actions performed for easy follow up
16 |
17 | ### Usecases ###
18 |
19 | * Audit request list (SOC2, C5, PCI DSS)
20 | * Gap analysis output (Any security gap list from any consultancy)
21 | * CVE check (Verify non-existence, not vulnerable or updated across many teams with report as evidence)
22 | * Quarterly security check output that needs to be remediated
23 | * Multi project upgrade work (e.g. all services need to upgrade encryption to TLS 1.3 or FIPS 140-3)
24 | * Output work from Datadog or Sumo Logic
25 |
26 |
27 | ## How do I get set up? ##
28 | * Normal Python 3.10 or higher setup should be followed, download Python here - https://www.python.org/downloads/.
29 | * A virtual environment should be set up `python -m venv .`
30 | * Activate the virtual environment `source venv/bin/activate` (this may be different on your system, check the created venv folder to ensure the path to the activate.py file is the same)
31 | * Install the imported packages `pip install -r requirements.txt` (this may be different on your system depending on the pip alias)
32 | * Set up a free instance of Jira Cloud `https://www.atlassian.com/software/jira/free`
33 | * This demo was set up with three Kanban, Company managed projects named 'Demo 1', 'Demo 2' and 'Demo 3' with keys 'D1', 'D2' and 'D3' for ease of following along, the user may wish to create these also.
34 | * This demo also has added two alternative emails so the user can see how the system reacts to users that are not the admin, this is not mandatory, however it is suggested the user do the same.
35 | * Create a copy of the .env_template file and name it `.env` exactly
36 | * Fill out the necessary fields in the newly created .env file (BASE_URL should look like this - https://YOURPROJECT.atlassian.net)
37 | * Your API token can be created by:
38 | 1. logging into Jira Cloud (the one you created earlier)
39 | 2. Click on your avatar in the top right
40 | 3. Click Account Settings
41 | 4. Navigate to the Security tab on the left
42 | 5. Click Create and manage API tokens
43 | * If creating stories from a CSV file, place it in the inputs folder to avoid sensitive data being committed to the repo.
44 | * If creating a report output file (Json files are outputted by some scripts), please put it in the reports folder to avoid sensitive data being committed to the repo.
45 |
46 |
47 | ## I'm set up, what's next? ##
48 | * The repository is set up in folders bringing the user from the basic operations through to the more complete solutions. Part 0 through to part 4.
49 | * Some functionality is offered in its own folder for easy transplanting into the learner's project for example assignable_users and emailer.
50 | * The just_for_fun folder is a collection of code used for pairing a presentation on this repository so is offered here as it may help someone down the line.
51 |
52 |
53 |
54 | * At present this is a collection of scripts that can be used independently or combined to accomplish more complex Jira tasks.
55 | * Some files committed to the repo are designed to accomplish specific goals and can serve as an example of how the different files can be combined.
56 | * To use the aws_emailer or GCP emailer an active account with separate credentials is needed.
57 |
58 |
59 | ### Contribution guidelines ###
60 |
61 | * Please contribute frequently and openly!
62 |
63 | ### Who do I talk to? ###
64 |
65 | * Original Creator - David Renton david.renton@genesys.com
66 |
--------------------------------------------------------------------------------
/part_3_creating_from_csv/_description_document.py:
--------------------------------------------------------------------------------
1 | # This file is imported by the part_3_create_in_projects_defined_in_csv.py and part_2_create_fancy_from_csv.py files
2 | # The json object assigned to fancy_description is generated from - https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/
3 |
4 | def description_doc(first_name, last_name, email, gender, ip_address, message):
5 | fancy_description = {
6 | "version": 1,
7 | "type": "doc",
8 | "content": [
9 | {
10 | "type": "heading",
11 | "attrs": {
12 | "level": 1
13 | },
14 | "content": [
15 | {
16 | "type": "text",
17 | "text": f"Hey {first_name} {last_name} "
18 | },
19 | {
20 | "type": "emoji",
21 | "attrs": {
22 | "shortName": ":wave:",
23 | "id": "1f44b",
24 | "text": "👋"
25 | }
26 | },
27 | {
28 | "type": "text",
29 | "text": " "
30 | }
31 | ]
32 | },
33 | {
34 | "type": "paragraph",
35 | "content": [
36 | {
37 | "type": "text",
38 | "text": "This story description was build "
39 | },
40 | {
41 | "type": "text",
42 | "text": "here",
43 | "marks": [
44 | {
45 | "type": "link",
46 | "attrs": {
47 | "href": "https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/"
48 | }
49 | }
50 | ]
51 | },
52 | {
53 | "type": "text",
54 | "text": " !"
55 | }
56 | ]
57 | },
58 | {
59 | "type": "paragraph",
60 | "content": [
61 | {
62 | "type": "text",
63 | "text": "Email, "
64 | },
65 | {
66 | "type": "text",
67 | "text": f"could have been used to assign the ticket {email}",
68 | "marks": [
69 | {
70 | "type": "em"
71 | }
72 | ]
73 | },
74 | {
75 | "type": "text",
76 | "text": " "
77 | },
78 | {
79 | "type": "emoji",
80 | "attrs": {
81 | "shortName": ":man_shrugging:",
82 | "id": "1f937-200d-2642-fe0f",
83 | "text": "🤷♂️"
84 | }
85 | },
86 | {
87 | "type": "text",
88 | "text": " "
89 | }
90 | ]
91 | },
92 | {
93 | "type": "bulletList",
94 | "content": [
95 | {
96 | "type": "listItem",
97 | "content": [
98 | {
99 | "type": "paragraph",
100 | "content": [
101 | {
102 | "type": "text",
103 | "text": f"Gender : {gender}"
104 | }
105 | ]
106 | }
107 | ]
108 | },
109 | {
110 | "type": "listItem",
111 | "content": [
112 | {
113 | "type": "paragraph",
114 | "content": [
115 | {
116 | "type": "text",
117 | "text": f"IP : {ip_address}"
118 | }
119 | ]
120 | }
121 | ]
122 | },
123 | {
124 | "type": "listItem",
125 | "content": [
126 | {
127 | "type": "paragraph",
128 | "content": [
129 | {
130 | "type": "text",
131 | "text": f"Message : {message}"
132 | }
133 | ]
134 | }
135 | ]
136 | }
137 | ]
138 | },
139 | {
140 | "type": "paragraph",
141 | "content": [
142 | {
143 | "type": "text",
144 | "text": "This is some code:"
145 | }
146 | ]
147 | },
148 | {
149 | "type": "codeBlock",
150 | "attrs": {
151 | "language": "python"
152 | },
153 | "content": [
154 | {
155 | "type": "text",
156 | "text": "res = create_issue(\n summary=f\"From CSV - {first_name} {last_name}\"\n , project=\"D2\"\n , description_doc=description_document\n , issue_type=\"Story\"\n , epic_link=\"D2-2\"\n , assignee_id=assignable_user_id\n , priority='High'\n)"
157 | }
158 | ]
159 | },
160 | {
161 | "type": "paragraph",
162 | "content": []
163 | }
164 | ]
165 | }
166 |
167 | return fancy_description
168 |
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/_description_document.py:
--------------------------------------------------------------------------------
1 | # This file is imported by the part_3_create_in_projects_defined_in_csv.py and part_2_create_fancy_from_csv.py files
2 | # The json object assigned to fancy_description is generated from - https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/
3 |
4 | def description_doc(first_name, last_name, email, gender, ip_address, message):
5 | fancy_description = {
6 | "version": 1,
7 | "type": "doc",
8 | "content": [
9 | {
10 | "type": "heading",
11 | "attrs": {
12 | "level": 1
13 | },
14 | "content": [
15 | {
16 | "type": "text",
17 | "text": f"Hey {first_name} {last_name} "
18 | },
19 | {
20 | "type": "emoji",
21 | "attrs": {
22 | "shortName": ":wave:",
23 | "id": "1f44b",
24 | "text": "👋"
25 | }
26 | },
27 | {
28 | "type": "text",
29 | "text": " "
30 | }
31 | ]
32 | },
33 | {
34 | "type": "paragraph",
35 | "content": [
36 | {
37 | "type": "text",
38 | "text": "This story description was build "
39 | },
40 | {
41 | "type": "text",
42 | "text": "here",
43 | "marks": [
44 | {
45 | "type": "link",
46 | "attrs": {
47 | "href": "https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/"
48 | }
49 | }
50 | ]
51 | },
52 | {
53 | "type": "text",
54 | "text": " !"
55 | }
56 | ]
57 | },
58 | {
59 | "type": "paragraph",
60 | "content": [
61 | {
62 | "type": "text",
63 | "text": "Email, "
64 | },
65 | {
66 | "type": "text",
67 | "text": f"could have been used to assign the ticket {email}",
68 | "marks": [
69 | {
70 | "type": "em"
71 | }
72 | ]
73 | },
74 | {
75 | "type": "text",
76 | "text": " "
77 | },
78 | {
79 | "type": "emoji",
80 | "attrs": {
81 | "shortName": ":man_shrugging:",
82 | "id": "1f937-200d-2642-fe0f",
83 | "text": "🤷♂️"
84 | }
85 | },
86 | {
87 | "type": "text",
88 | "text": " "
89 | }
90 | ]
91 | },
92 | {
93 | "type": "bulletList",
94 | "content": [
95 | {
96 | "type": "listItem",
97 | "content": [
98 | {
99 | "type": "paragraph",
100 | "content": [
101 | {
102 | "type": "text",
103 | "text": f"Gender : {gender}"
104 | }
105 | ]
106 | }
107 | ]
108 | },
109 | {
110 | "type": "listItem",
111 | "content": [
112 | {
113 | "type": "paragraph",
114 | "content": [
115 | {
116 | "type": "text",
117 | "text": f"IP : {ip_address}"
118 | }
119 | ]
120 | }
121 | ]
122 | },
123 | {
124 | "type": "listItem",
125 | "content": [
126 | {
127 | "type": "paragraph",
128 | "content": [
129 | {
130 | "type": "text",
131 | "text": f"Message : {message}"
132 | }
133 | ]
134 | }
135 | ]
136 | }
137 | ]
138 | },
139 | {
140 | "type": "paragraph",
141 | "content": [
142 | {
143 | "type": "text",
144 | "text": "This is some code:"
145 | }
146 | ]
147 | },
148 | {
149 | "type": "codeBlock",
150 | "attrs": {
151 | "language": "python"
152 | },
153 | "content": [
154 | {
155 | "type": "text",
156 | "text": "res = create_issue(\n summary=f\"From CSV - {first_name} {last_name}\"\n , project=\"D2\"\n , description_doc=description_document\n , issue_type=\"Story\"\n , epic_link=\"D2-2\"\n , assignee_id=assignable_user_id\n , priority='High'\n)"
157 | }
158 | ]
159 | },
160 | {
161 | "type": "paragraph",
162 | "content": []
163 | }
164 | ]
165 | }
166 |
167 | return fancy_description
168 |
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/part_2_create_assign_email_prepaired_for_follow_up.py:
--------------------------------------------------------------------------------
1 | import csv
2 | import hashlib
3 | import json
4 | import os
5 | from datetime import datetime
6 |
7 | from src import get_all_assignable_users_email
8 | from src import create_fancy_issue
9 | from emailer.aws_emailer.email_with_attachment import send_mail
10 | from part_4_creating_assigning_and_emailing._description_document import description_doc
11 | from part_4_creating_assigning_and_emailing._email_body import email_body
12 |
13 | assignable_users = get_all_assignable_users_email('D1')
14 |
15 |
16 | def main(file_, epic_, initiative_name_):
17 | init_ = {}
18 | f_name = f"reports/{initiative_name_}.json"
19 | if os.path.exists(f_name):
20 | with open(f'reports/{initiative_name_}.json', 'r+') as initiative_:
21 | init_ = json.load(initiative_)
22 | else:
23 | init_['created'] = []
24 | init_['stories'] = {}
25 | with open(file_) as infile:
26 | reader = csv.reader(infile, delimiter=",")
27 | # Skip the header
28 | next(reader, None)
29 | # For each row
30 | for row in reader:
31 | row_tuple = tuple(row)
32 | hash_ = hashlib.md5()
33 | for entry in row_tuple:
34 | hash_.update(entry.encode())
35 | row_hash = hash_.hexdigest()
36 | # Are we doing work or not?
37 | if row_hash not in init_['created']:
38 | # get user id from email, this could be provided in th csv file
39 | date_ = datetime.now()
40 | assignable_user_email = 'davidleerenton@gmail.com'
41 | assignable_user_id = assignable_users.get(assignable_user_email, None)
42 | # these don't need to be assigned, this way just makes it more readable when debugging.
43 | first_name = row[1]
44 | last_name = row[2]
45 | email = row[3]
46 | gender = row[4]
47 | ip_address = row[5]
48 | message = row[6]
49 | project = row[7]
50 | # Create the description document
51 | description_document = description_doc(first_name, last_name, email, gender, ip_address, message)
52 | # Build and execute the call to the Jira Cloud API
53 | try:
54 | res = create_fancy_issue(
55 | summary=f"From CSV - {first_name} {last_name}"
56 | , project=project
57 | , description_doc=description_document
58 | , issue_type="Story"
59 | , epic_link=epic_
60 | , assignee_id=assignable_user_id
61 | , priority='High'
62 | )
63 | json_res = json.loads(res.text)
64 | story_key = json_res['key']
65 | init_['stories'][f'{story_key}'] = {
66 | "date_opened": f"{date_}",
67 | "assignee": f"{assignable_user_email}",
68 | "assignee_id": f"{assignable_user_id}",
69 | "hash": f"{row_hash}",
70 | "status_category": "new",
71 | "reminder": []
72 | }
73 | init_['created'].append(row_hash)
74 | except Exception as e:
75 | with open(f'reports/{initiative_name_}.json', 'w') as outfile:
76 | json.dump(init_, outfile)
77 | print(f"Exception: {e} \nFor: {row}")
78 |
79 | sender_ = 'david.renton@genesys.com'
80 | recipients_ = [f'{assignable_user_email}']
81 | cc_ = ['davidleerenton@gmail.com', 'hello@devfestireland.com']
82 | title_ = 'DevFest Ireland'
83 | text_ = 'DevFest is awesome'
84 | body_ = email_body(first_name, last_name, gender, ip_address, message, project, story_key)
85 | attachments_ = ['input/devfestireland_with_image.png']
86 | try:
87 | response_ = send_mail(sender_, recipients_, cc_, title_, text_, body_, attachments_)
88 | print(response_)
89 | init_['stories'][f'{story_key}']['reminder'].append(f"Email with subject {title_} was sent to {recipients_} on {date_}")
90 | except:
91 | with open(f'reports/{initiative_name_}.json', 'w') as outfile:
92 | json.dump(init_, outfile)
93 | with open(f'reports/{initiative_name_}.json', 'w') as outfile:
94 | json.dump(init_, outfile)
95 |
96 |
97 | if __name__ == "__main__":
98 | initiative_name = "go_to_devfest"
99 | input_file = "input/MOCK_DATA_WITH_PROJECT.csv"
100 | epic = "D2-2"
101 | main(input_file, epic, initiative_name)
102 |
103 | with open(f'reports/{initiative_name}.json', 'r+') as initiative:
104 | init = json.load(initiative)
105 | print(json.dumps(init, indent=4))
106 |
107 | # # Some stories got added
108 | # ready_to_add_some_more = input("Ready to add more stories?")
109 | # initiative_name = "go_to_devfest"
110 | # input_file = "input/MOCK_DATA_WITH_PROJECT_6_lines.csv"
111 | # main(input_file, epic, initiative_name)
112 | #
113 | # ready_to_see_the_result_2 = input("press any key")
114 | # with open(f'reports/{initiative_name}.json', 'r+') as initiative:
115 | # init = json.load(initiative)
116 | # print(json.dumps(init, indent=4))
117 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | david.renton@genesys.com.
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/src/jirascripting/create_fancy_jira_issue.py:
--------------------------------------------------------------------------------
1 | import json
2 | import requests
3 | from src.jirascripting.auth_and_headers import jira_auth_and_headers
4 |
5 |
6 | def create_fancy_issue(summary, project, description_doc, parent=None, assignee_id=None, priority="High", issue_type="Story"):
7 | """Creates an ADF(markdown) story under an epic, use the pyadf library to build out the description document
8 | https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/
9 |
10 | Parameters:
11 | :param summary: (string) The issue summary.
12 | :param project: (string) Project key eg. D1-1.
13 | :param description_doc: (string) Use the Document Builder here https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/.
14 | :param parent: (string): The key of the parent epic
15 | :param assignee_id: (string) The ID of the assignable user (use get_assignable_users to get this).
16 | :param issue_type: (string) Text name of the issue type you wish to create eg, Story, Bug, Task
17 | :param priority: (string) Text - Highest, High, Medium, Low, Lowest
18 |
19 | Returns:
20 | response object: This will have the response code and in the text will have the details of the created issue.
21 |
22 | """
23 | auth, headers, base_url = jira_auth_and_headers()
24 |
25 | # create issue
26 | issue = {'fields': {}}
27 | if parent is not None:
28 | issue['fields']['parent'] = {'key': parent}
29 | issue['fields']['summary'] = summary
30 | issue['fields']['issuetype'] = {'name': issue_type}
31 | issue['fields']['project'] = {'key': project}
32 | issue['fields']['description'] = description_doc
33 | issue['fields']['priority'] = {'name': priority}
34 | if assignee_id is not None:
35 | issue['fields']['assignee'] = {'id': assignee_id}
36 | else:
37 | issue['fields']['assignee'] = {'id': "-1"}
38 |
39 | url = f"{base_url}/rest/api/3/issue"
40 | payload = json.dumps(issue)
41 | response = requests.request(
42 | "POST",
43 | url,
44 | data=payload,
45 | headers=headers,
46 | auth=auth
47 | )
48 | return response
49 |
50 |
51 | if __name__ == "__main__":
52 | formatted_description = {
53 | "version": 1,
54 | "type": "doc",
55 | "content": [
56 | {
57 | "type": "paragraph",
58 | "content": [
59 | {
60 | "type": "text",
61 | "text": "Generated from the "
62 | },
63 | {
64 | "type": "text",
65 | "text": "Document Builder",
66 | "marks": [
67 | {
68 | "type": "link",
69 | "attrs": {
70 | "href": "https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/"
71 | }
72 | }
73 | ]
74 | }
75 | ]
76 | },
77 | {
78 | "type": "paragraph",
79 | "content": [
80 | {
81 | "type": "text",
82 | "text": "I am bold",
83 | "marks": [
84 | {
85 | "type": "strong"
86 | }
87 | ]
88 | }
89 | ]
90 | },
91 | {
92 | "type": "paragraph",
93 | "content": [
94 | {
95 | "type": "text",
96 | "text": "I am itallic",
97 | "marks": [
98 | {
99 | "type": "em"
100 | }
101 | ]
102 | }
103 | ]
104 | },
105 | {
106 | "type": "paragraph",
107 | "content": [
108 | {
109 | "type": "text",
110 | "text": "List"
111 | }
112 | ]
113 | },
114 | {
115 | "type": "bulletList",
116 | "content": [
117 | {
118 | "type": "listItem",
119 | "content": [
120 | {
121 | "type": "paragraph",
122 | "content": [
123 | {
124 | "type": "text",
125 | "text": "one"
126 | }
127 | ]
128 | }
129 | ]
130 | },
131 | {
132 | "type": "listItem",
133 | "content": [
134 | {
135 | "type": "paragraph",
136 | "content": [
137 | {
138 | "type": "text",
139 | "text": "two"
140 | }
141 | ]
142 | }
143 | ]
144 | },
145 | {
146 | "type": "listItem",
147 | "content": [
148 | {
149 | "type": "paragraph",
150 | "content": [
151 | {
152 | "type": "text",
153 | "text": "three"
154 | }
155 | ]
156 | }
157 | ]
158 | }
159 | ]
160 | },
161 | {
162 | "type": "paragraph",
163 | "content": []
164 | },
165 | {
166 | "type": "codeBlock",
167 | "attrs": {
168 | "language": "python"
169 | },
170 | "content": [
171 | {
172 | "type": "text",
173 | "text": "def some_python_method():\n me = some_variable\n return me"
174 | }
175 | ]
176 | }
177 | ]
178 | }
179 | res = create_fancy_issue(
180 | summary="MarkDown Test"
181 | , project="D1"
182 | , description_doc=formatted_description
183 | , issue_type="Story"
184 | # , epic_link="SECCOMPPM-6"
185 | , assignee_id="557058:e747a920-b560-47ee-82e3-94ffe7a59a1b"
186 | , priority='High'
187 | )
188 | if res.status_code == 400:
189 | json_res = json.loads(res.text)
190 | print(json_res['errors'])
191 | else:
192 | json_res = json.loads(res.text)
193 | story_id = json_res['id']
194 | story_key = json_res['key']
195 | print(f"ID: {story_id}, Key: {story_key} ")
196 |
--------------------------------------------------------------------------------
/just_for_fun/file_access/input/MOCK_DATA.csv:
--------------------------------------------------------------------------------
1 | id,first_name,last_name,email,gender,ip_address,message
2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor
3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus
4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui
5 | 4,Morlee,Summerton,msummerton3@youtube.com,Male,221.95.67.170,quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie
6 | 5,Adler,Steptow,asteptow4@bizjournals.com,Male,215.156.252.103,quis tortor id nulla ultrices aliquet maecenas leo odio condimentum
7 | 6,Susanetta,Peach,speach5@about.com,Female,199.21.109.212,a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue vestibulum
8 | 7,Waring,Rouby,wrouby6@ihg.com,Male,199.21.3.154,parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida
9 | 8,Farra,Adanet,fadanet7@4shared.com,Female,11.117.37.31,sociis natoque penatibus et magnis dis parturient montes nascetur ridiculus
10 | 9,Zonnya,Van,zvan8@ftc.gov,Female,66.253.168.84,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in faucibus
11 | 10,Jonathan,Cherrett,jcherrett9@admin.ch,Male,28.20.34.252,laoreet ut rhoncus aliquet pulvinar sed nisl nunc rhoncus dui vel sem sed
12 | 11,Ramona,Rispine,rrispinea@cnet.com,Female,149.48.48.207,in purus eu magna vulputate luctus cum sociis natoque penatibus et magnis dis parturient montes nascetur
13 | 12,Bidget,Tanby,btanbyb@miitbeian.gov.cn,Bigender,86.185.76.82,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec
14 | 13,Tim,Juanico,tjuanicoc@nsw.gov.au,Male,100.231.76.87,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum
15 | 14,Mariann,Valentelli,mvalentellid@nature.com,Female,236.199.109.232,cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat
16 | 15,Francois,Macek,fmaceke@ning.com,Male,134.86.61.194,interdum in ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia
17 | 16,Lise,Stuehmeier,lstuehmeierf@narod.ru,Female,201.135.223.48,magnis dis parturient montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis
18 | 17,Jule,Coley,jcoleyg@cnet.com,Male,50.18.145.153,sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie
19 | 18,Shelia,Condy,scondyh@businessinsider.com,Bigender,133.163.110.102,lobortis ligula sit amet eleifend pede libero quis orci nullam molestie nibh
20 | 19,Nickolas,Lurcock,nlurcocki@xing.com,Male,15.0.79.220,ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti
21 | 20,Beauregard,Leving,blevingj@exblog.jp,Male,105.122.125.150,orci eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu
22 | 21,Ephraim,Comini,ecominik@creativecommons.org,Male,225.164.139.15,ligula pellentesque ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at
23 | 22,Serge,Warmington,swarmingtonl@a8.net,Male,31.38.85.191,molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec
24 | 23,Mar,Rickman,mrickmanm@ucoz.com,Male,123.145.218.101,lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper
25 | 24,Ashlan,Rycraft,arycraftn@phoca.cz,Female,27.60.25.138,sed vel enim sit amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac
26 | 25,Beatrice,Antonoyev,bantonoyevo@fotki.com,Female,222.35.15.241,at feugiat non pretium quis lectus suspendisse potenti in eleifend
27 | 26,Sandy,Cockshott,scockshottp@umn.edu,Female,29.121.131.207,erat eros viverra eget congue eget semper rutrum nulla nunc purus phasellus in
28 | 27,Barnie,Spieck,bspieckq@ycombinator.com,Male,83.191.46.104,turpis a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue
29 | 28,Augustin,Mildmott,amildmottr@dedecms.com,Genderqueer,22.198.173.45,rutrum rutrum neque aenean auctor gravida sem praesent id massa id nisl
30 | 29,Clem,Verbeke,cverbekes@webmd.com,Male,96.55.88.58,eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in
31 | 30,Leland,Oene,loenet@merriam-webster.com,Female,184.8.16.13,ligula nec sem duis aliquam convallis nunc proin at turpis a pede posuere
32 | 31,Greggory,Tadman,gtadmanu@unesco.org,Male,109.228.187.124,luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet
33 | 32,Tandy,Tilliard,ttilliardv@msu.edu,Polygender,169.88.229.190,integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia sapien quis
34 | 33,Ondrea,Gibbens,ogibbensw@odnoklassniki.ru,Female,230.131.21.204,eleifend donec ut dolor morbi vel lectus in quam fringilla rhoncus mauris enim leo rhoncus
35 | 34,Claire,Jellett,cjellettx@npr.org,Female,237.142.247.207,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu
36 | 35,Patrica,Docwra,pdocwray@loc.gov,Female,57.68.189.196,volutpat quam pede lobortis ligula sit amet eleifend pede libero quis
37 | 36,Ludovico,Durrand,ldurrandz@vkontakte.ru,Male,213.204.107.140,a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id
38 | 37,Brandyn,Enrietto,benrietto10@reference.com,Male,71.85.30.227,in faucibus orci luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet
39 | 38,Pavel,Shury,pshury11@cyberchimps.com,Male,9.122.13.127,pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat metus
40 | 39,Korney,Radsdale,kradsdale12@adobe.com,Agender,11.31.223.56,mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit
41 | 40,Filmer,Brugman,fbrugman13@slate.com,Male,8.194.92.208,fusce consequat nulla nisl nunc nisl duis bibendum felis sed interdum
42 | 41,Artus,McQuaker,amcquaker14@europa.eu,Male,165.194.178.43,integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue
43 | 42,Shaughn,Clarage,sclarage15@csmonitor.com,Male,133.166.203.189,proin at turpis a pede posuere nonummy integer non velit donec diam neque vestibulum
44 | 43,Sal,Townrow,stownrow16@mit.edu,Male,186.233.158.243,porttitor id consequat in consequat ut nulla sed accumsan felis ut
45 | 44,Laurens,Suero,lsuero17@theguardian.com,Male,91.138.55.164,libero convallis eget eleifend luctus ultricies eu nibh quisque id justo sit amet sapien dignissim
46 | 45,Whitaker,Fray,wfray18@typepad.com,Male,15.202.52.204,luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec
47 | 46,Lodovico,Kilmurray,lkilmurray19@pbs.org,Male,133.52.192.14,in porttitor pede justo eu massa donec dapibus duis at velit eu est congue
48 | 47,Zeb,Jago,zjago1a@amazon.co.jp,Male,33.172.134.241,leo odio porttitor id consequat in consequat ut nulla sed
49 | 48,Kenyon,Kembry,kkembry1b@usda.gov,Male,57.219.244.202,ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at
50 | 49,Emilio,Murfill,emurfill1c@geocities.jp,Male,125.85.233.66,feugiat et eros vestibulum ac est lacinia nisi venenatis tristique fusce congue diam id ornare imperdiet sapien
51 | 50,Ruggiero,McGahy,rmcgahy1d@usda.gov,Male,174.102.12.131,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in
52 | 51,Lou,Mulvaney,lmulvaney1e@independent.co.uk,Female,185.156.141.80,faucibus accumsan odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut dolor morbi
53 | 52,Rodie,Kopfer,rkopfer1f@thetimes.co.uk,Female,236.130.221.23,metus arcu adipiscing molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci vehicula
54 | 53,Tabbatha,Headon,theadon1g@bloglovin.com,Female,29.182.214.92,ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi
55 | 54,Casper,Kleinsmuntz,ckleinsmuntz1h@time.com,Non-binary,241.198.185.114,auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit amet justo morbi ut odio cras mi
56 | 55,Felike,Meriott,fmeriott1i@nbcnews.com,Male,74.9.71.45,erat fermentum justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget elit sodales scelerisque mauris
57 | 56,Jone,Startin,jstartin1j@go.com,Male,222.163.247.254,ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque
58 | 57,Robbie,Bardwell,rbardwell1k@eventbrite.com,Female,31.32.82.2,pretium iaculis justo in hac habitasse platea dictumst etiam faucibus cursus urna ut tellus
59 | 58,Valida,Fordy,vfordy1l@ebay.com,Female,200.107.191.6,duis aliquam convallis nunc proin at turpis a pede posuere nonummy integer
60 | 59,Carline,Muslim,cmuslim1m@google.nl,Female,135.156.143.43,tincidunt eget tempus vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus
61 | 60,Lindsy,Crampsy,lcrampsy1n@pbs.org,Female,196.28.176.125,lacus at turpis donec posuere metus vitae ipsum aliquam non mauris morbi non lectus aliquam sit amet diam
62 | 61,Lorain,Daveran,ldaveran1o@tinypic.com,Female,32.161.81.252,sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer
63 | 62,Joelie,Babbage,jbabbage1p@businessinsider.com,Female,40.16.148.236,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam
64 | 63,Rob,Camble,rcamble1q@theguardian.com,Male,46.16.134.71,et ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus
65 | 64,Pete,Butterfint,pbutterfint1r@globo.com,Male,103.180.67.203,pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet nunc viverra
66 | 65,Camey,McCorrie,cmccorrie1s@scribd.com,Bigender,160.40.98.81,in congue etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst etiam faucibus
67 | 66,Charlton,Rattenberie,crattenberie1t@bbc.co.uk,Genderqueer,225.201.157.166,euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis nunc proin
68 | 67,Wayne,Squelch,wsquelch1u@statcounter.com,Male,34.162.46.167,tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum ac lobortis vel dapibus at diam nam
69 | 68,Dusty,Orknay,dorknay1v@google.cn,Female,164.168.241.160,mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in hac habitasse platea dictumst aliquam augue quam sollicitudin
70 | 69,Marietta,Henrych,mhenrych1w@posterous.com,Male,144.205.241.125,nonummy maecenas tincidunt lacus at velit vivamus vel nulla eget eros elementum pellentesque quisque porta volutpat
71 | 70,Seward,Wines,swines1x@dion.ne.jp,Male,179.111.158.128,justo eu massa donec dapibus duis at velit eu est congue elementum in hac habitasse platea dictumst morbi
72 | 71,Brandie,Dishmon,bdishmon1y@accuweather.com,Female,43.198.111.81,velit donec diam neque vestibulum eget vulputate ut ultrices vel augue
73 | 72,Krispin,Hawkes,khawkes1z@goo.gl,Male,25.243.0.47,amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper purus sit
74 | 73,Lenci,Quarrie,lquarrie20@hexun.com,Male,128.155.226.204,convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia
75 | 74,Ettie,Mew,emew21@oakley.com,Female,241.248.54.155,erat curabitur gravida nisi at nibh in hac habitasse platea
76 | 75,Van,Snook,vsnook22@qq.com,Male,61.219.61.202,tortor risus dapibus augue vel accumsan tellus nisi eu orci
77 | 76,Olenolin,Mulroy,omulroy23@latimes.com,Male,226.135.112.198,mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a
78 | 77,Annabelle,Feuell,afeuell24@miibeian.gov.cn,Female,67.132.7.234,blandit lacinia erat vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede justo lacinia eget
79 | 78,Freeland,Davydenko,fdavydenko25@dmoz.org,Male,142.8.61.193,non mauris morbi non lectus aliquam sit amet diam in magna bibendum imperdiet
80 | 79,Dolf,Norkett,dnorkett26@weather.com,Male,171.106.145.215,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu felis fusce posuere
81 | 80,Murry,Kettridge,mkettridge27@pagesperso-orange.fr,Male,89.26.132.166,non mi integer ac neque duis bibendum morbi non quam nec
82 | 81,Neill,Bockett,nbockett28@moonfruit.com,Male,178.228.106.179,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra
83 | 82,Erroll,Cressy,ecressy29@uol.com.br,Male,80.2.18.106,hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci
84 | 83,Yorgos,Ropcke,yropcke2a@census.gov,Male,15.186.0.137,maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet maecenas leo
85 | 84,Freddy,Sirey,fsirey2b@bandcamp.com,Female,239.243.25.52,rutrum rutrum neque aenean auctor gravida sem praesent id massa id
86 | 85,Irita,Tamplin,itamplin2c@tmall.com,Female,244.230.38.59,quis orci nullam molestie nibh in lectus pellentesque at nulla suspendisse potenti
87 | 86,Sol,Iacopo,siacopo2d@hugedomains.com,Male,148.13.113.71,justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget
88 | 87,Waiter,Flemmich,wflemmich2e@archive.org,Male,119.196.69.233,odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut
89 | 88,Gayle,Korba,gkorba2f@japanpost.jp,Female,101.227.66.137,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum
90 | 89,Aeriel,Januszewski,ajanuszewski2g@europa.eu,Female,44.187.117.9,etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst
91 | 90,Frazier,Pickworth,fpickworth2h@pcworld.com,Male,192.241.214.249,posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus vitae
92 | 91,Rafi,Karolczyk,rkarolczyk2i@ca.gov,Male,58.176.232.103,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla
93 | 92,Dante,Rymell,drymell2j@cpanel.net,Male,154.34.140.144,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum mauris non ligula pellentesque
94 | 93,Darla,Feely,dfeely2k@unc.edu,Female,234.119.129.183,montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis dis parturient montes
95 | 94,Seymour,Densey,sdensey2l@51.la,Male,13.211.116.247,in tempus sit amet sem fusce consequat nulla nisl nunc
96 | 95,Alano,Blague,ablague2m@ftc.gov,Male,194.113.170.18,faucibus orci luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec nisi
97 | 96,Bartlett,Trounce,btrounce2n@bandcamp.com,Male,41.31.216.254,eleifend quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem
98 | 97,Mandel,Silliman,msilliman2o@google.com.br,Male,92.27.219.21,aenean auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit
99 | 98,Gerrard,Moxon,gmoxon2p@wikispaces.com,Male,58.246.131.46,id justo sit amet sapien dignissim vestibulum vestibulum ante ipsum primis in faucibus orci
100 | 99,Meryl,Rossey,mrossey2q@sun.com,Female,26.223.20.51,ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae duis
101 | 100,Sholom,Bengtsen,sbengtsen2r@google.co.jp,Male,39.44.28.105,cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam
102 |
--------------------------------------------------------------------------------
/part_3_creating_from_csv/input/MOCK_DATA.csv:
--------------------------------------------------------------------------------
1 | id,first_name,last_name,email,gender,ip_address,message
2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor
3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus
4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui
5 | 4,Morlee,Summerton,msummerton3@youtube.com,Male,221.95.67.170,quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie
6 | 5,Adler,Steptow,asteptow4@bizjournals.com,Male,215.156.252.103,quis tortor id nulla ultrices aliquet maecenas leo odio condimentum
7 | 6,Susanetta,Peach,speach5@about.com,Female,199.21.109.212,a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue vestibulum
8 | 7,Waring,Rouby,wrouby6@ihg.com,Male,199.21.3.154,parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida
9 | 8,Farra,Adanet,fadanet7@4shared.com,Female,11.117.37.31,sociis natoque penatibus et magnis dis parturient montes nascetur ridiculus
10 | 9,Zonnya,Van,zvan8@ftc.gov,Female,66.253.168.84,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in faucibus
11 | 10,Jonathan,Cherrett,jcherrett9@admin.ch,Male,28.20.34.252,laoreet ut rhoncus aliquet pulvinar sed nisl nunc rhoncus dui vel sem sed
12 | 11,Ramona,Rispine,rrispinea@cnet.com,Female,149.48.48.207,in purus eu magna vulputate luctus cum sociis natoque penatibus et magnis dis parturient montes nascetur
13 | 12,Bidget,Tanby,btanbyb@miitbeian.gov.cn,Bigender,86.185.76.82,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec
14 | 13,Tim,Juanico,tjuanicoc@nsw.gov.au,Male,100.231.76.87,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum
15 | 14,Mariann,Valentelli,mvalentellid@nature.com,Female,236.199.109.232,cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat
16 | 15,Francois,Macek,fmaceke@ning.com,Male,134.86.61.194,interdum in ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia
17 | 16,Lise,Stuehmeier,lstuehmeierf@narod.ru,Female,201.135.223.48,magnis dis parturient montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis
18 | 17,Jule,Coley,jcoleyg@cnet.com,Male,50.18.145.153,sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie
19 | 18,Shelia,Condy,scondyh@businessinsider.com,Bigender,133.163.110.102,lobortis ligula sit amet eleifend pede libero quis orci nullam molestie nibh
20 | 19,Nickolas,Lurcock,nlurcocki@xing.com,Male,15.0.79.220,ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti
21 | 20,Beauregard,Leving,blevingj@exblog.jp,Male,105.122.125.150,orci eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu
22 | 21,Ephraim,Comini,ecominik@creativecommons.org,Male,225.164.139.15,ligula pellentesque ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at
23 | 22,Serge,Warmington,swarmingtonl@a8.net,Male,31.38.85.191,molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec
24 | 23,Mar,Rickman,mrickmanm@ucoz.com,Male,123.145.218.101,lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper
25 | 24,Ashlan,Rycraft,arycraftn@phoca.cz,Female,27.60.25.138,sed vel enim sit amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac
26 | 25,Beatrice,Antonoyev,bantonoyevo@fotki.com,Female,222.35.15.241,at feugiat non pretium quis lectus suspendisse potenti in eleifend
27 | 26,Sandy,Cockshott,scockshottp@umn.edu,Female,29.121.131.207,erat eros viverra eget congue eget semper rutrum nulla nunc purus phasellus in
28 | 27,Barnie,Spieck,bspieckq@ycombinator.com,Male,83.191.46.104,turpis a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue
29 | 28,Augustin,Mildmott,amildmottr@dedecms.com,Genderqueer,22.198.173.45,rutrum rutrum neque aenean auctor gravida sem praesent id massa id nisl
30 | 29,Clem,Verbeke,cverbekes@webmd.com,Male,96.55.88.58,eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in
31 | 30,Leland,Oene,loenet@merriam-webster.com,Female,184.8.16.13,ligula nec sem duis aliquam convallis nunc proin at turpis a pede posuere
32 | 31,Greggory,Tadman,gtadmanu@unesco.org,Male,109.228.187.124,luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet
33 | 32,Tandy,Tilliard,ttilliardv@msu.edu,Polygender,169.88.229.190,integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia sapien quis
34 | 33,Ondrea,Gibbens,ogibbensw@odnoklassniki.ru,Female,230.131.21.204,eleifend donec ut dolor morbi vel lectus in quam fringilla rhoncus mauris enim leo rhoncus
35 | 34,Claire,Jellett,cjellettx@npr.org,Female,237.142.247.207,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu
36 | 35,Patrica,Docwra,pdocwray@loc.gov,Female,57.68.189.196,volutpat quam pede lobortis ligula sit amet eleifend pede libero quis
37 | 36,Ludovico,Durrand,ldurrandz@vkontakte.ru,Male,213.204.107.140,a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id
38 | 37,Brandyn,Enrietto,benrietto10@reference.com,Male,71.85.30.227,in faucibus orci luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet
39 | 38,Pavel,Shury,pshury11@cyberchimps.com,Male,9.122.13.127,pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat metus
40 | 39,Korney,Radsdale,kradsdale12@adobe.com,Agender,11.31.223.56,mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit
41 | 40,Filmer,Brugman,fbrugman13@slate.com,Male,8.194.92.208,fusce consequat nulla nisl nunc nisl duis bibendum felis sed interdum
42 | 41,Artus,McQuaker,amcquaker14@europa.eu,Male,165.194.178.43,integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue
43 | 42,Shaughn,Clarage,sclarage15@csmonitor.com,Male,133.166.203.189,proin at turpis a pede posuere nonummy integer non velit donec diam neque vestibulum
44 | 43,Sal,Townrow,stownrow16@mit.edu,Male,186.233.158.243,porttitor id consequat in consequat ut nulla sed accumsan felis ut
45 | 44,Laurens,Suero,lsuero17@theguardian.com,Male,91.138.55.164,libero convallis eget eleifend luctus ultricies eu nibh quisque id justo sit amet sapien dignissim
46 | 45,Whitaker,Fray,wfray18@typepad.com,Male,15.202.52.204,luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec
47 | 46,Lodovico,Kilmurray,lkilmurray19@pbs.org,Male,133.52.192.14,in porttitor pede justo eu massa donec dapibus duis at velit eu est congue
48 | 47,Zeb,Jago,zjago1a@amazon.co.jp,Male,33.172.134.241,leo odio porttitor id consequat in consequat ut nulla sed
49 | 48,Kenyon,Kembry,kkembry1b@usda.gov,Male,57.219.244.202,ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at
50 | 49,Emilio,Murfill,emurfill1c@geocities.jp,Male,125.85.233.66,feugiat et eros vestibulum ac est lacinia nisi venenatis tristique fusce congue diam id ornare imperdiet sapien
51 | 50,Ruggiero,McGahy,rmcgahy1d@usda.gov,Male,174.102.12.131,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in
52 | 51,Lou,Mulvaney,lmulvaney1e@independent.co.uk,Female,185.156.141.80,faucibus accumsan odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut dolor morbi
53 | 52,Rodie,Kopfer,rkopfer1f@thetimes.co.uk,Female,236.130.221.23,metus arcu adipiscing molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci vehicula
54 | 53,Tabbatha,Headon,theadon1g@bloglovin.com,Female,29.182.214.92,ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi
55 | 54,Casper,Kleinsmuntz,ckleinsmuntz1h@time.com,Non-binary,241.198.185.114,auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit amet justo morbi ut odio cras mi
56 | 55,Felike,Meriott,fmeriott1i@nbcnews.com,Male,74.9.71.45,erat fermentum justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget elit sodales scelerisque mauris
57 | 56,Jone,Startin,jstartin1j@go.com,Male,222.163.247.254,ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque
58 | 57,Robbie,Bardwell,rbardwell1k@eventbrite.com,Female,31.32.82.2,pretium iaculis justo in hac habitasse platea dictumst etiam faucibus cursus urna ut tellus
59 | 58,Valida,Fordy,vfordy1l@ebay.com,Female,200.107.191.6,duis aliquam convallis nunc proin at turpis a pede posuere nonummy integer
60 | 59,Carline,Muslim,cmuslim1m@google.nl,Female,135.156.143.43,tincidunt eget tempus vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus
61 | 60,Lindsy,Crampsy,lcrampsy1n@pbs.org,Female,196.28.176.125,lacus at turpis donec posuere metus vitae ipsum aliquam non mauris morbi non lectus aliquam sit amet diam
62 | 61,Lorain,Daveran,ldaveran1o@tinypic.com,Female,32.161.81.252,sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer
63 | 62,Joelie,Babbage,jbabbage1p@businessinsider.com,Female,40.16.148.236,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam
64 | 63,Rob,Camble,rcamble1q@theguardian.com,Male,46.16.134.71,et ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus
65 | 64,Pete,Butterfint,pbutterfint1r@globo.com,Male,103.180.67.203,pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet nunc viverra
66 | 65,Camey,McCorrie,cmccorrie1s@scribd.com,Bigender,160.40.98.81,in congue etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst etiam faucibus
67 | 66,Charlton,Rattenberie,crattenberie1t@bbc.co.uk,Genderqueer,225.201.157.166,euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis nunc proin
68 | 67,Wayne,Squelch,wsquelch1u@statcounter.com,Male,34.162.46.167,tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum ac lobortis vel dapibus at diam nam
69 | 68,Dusty,Orknay,dorknay1v@google.cn,Female,164.168.241.160,mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in hac habitasse platea dictumst aliquam augue quam sollicitudin
70 | 69,Marietta,Henrych,mhenrych1w@posterous.com,Male,144.205.241.125,nonummy maecenas tincidunt lacus at velit vivamus vel nulla eget eros elementum pellentesque quisque porta volutpat
71 | 70,Seward,Wines,swines1x@dion.ne.jp,Male,179.111.158.128,justo eu massa donec dapibus duis at velit eu est congue elementum in hac habitasse platea dictumst morbi
72 | 71,Brandie,Dishmon,bdishmon1y@accuweather.com,Female,43.198.111.81,velit donec diam neque vestibulum eget vulputate ut ultrices vel augue
73 | 72,Krispin,Hawkes,khawkes1z@goo.gl,Male,25.243.0.47,amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper purus sit
74 | 73,Lenci,Quarrie,lquarrie20@hexun.com,Male,128.155.226.204,convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia
75 | 74,Ettie,Mew,emew21@oakley.com,Female,241.248.54.155,erat curabitur gravida nisi at nibh in hac habitasse platea
76 | 75,Van,Snook,vsnook22@qq.com,Male,61.219.61.202,tortor risus dapibus augue vel accumsan tellus nisi eu orci
77 | 76,Olenolin,Mulroy,omulroy23@latimes.com,Male,226.135.112.198,mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a
78 | 77,Annabelle,Feuell,afeuell24@miibeian.gov.cn,Female,67.132.7.234,blandit lacinia erat vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede justo lacinia eget
79 | 78,Freeland,Davydenko,fdavydenko25@dmoz.org,Male,142.8.61.193,non mauris morbi non lectus aliquam sit amet diam in magna bibendum imperdiet
80 | 79,Dolf,Norkett,dnorkett26@weather.com,Male,171.106.145.215,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu felis fusce posuere
81 | 80,Murry,Kettridge,mkettridge27@pagesperso-orange.fr,Male,89.26.132.166,non mi integer ac neque duis bibendum morbi non quam nec
82 | 81,Neill,Bockett,nbockett28@moonfruit.com,Male,178.228.106.179,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra
83 | 82,Erroll,Cressy,ecressy29@uol.com.br,Male,80.2.18.106,hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci
84 | 83,Yorgos,Ropcke,yropcke2a@census.gov,Male,15.186.0.137,maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet maecenas leo
85 | 84,Freddy,Sirey,fsirey2b@bandcamp.com,Female,239.243.25.52,rutrum rutrum neque aenean auctor gravida sem praesent id massa id
86 | 85,Irita,Tamplin,itamplin2c@tmall.com,Female,244.230.38.59,quis orci nullam molestie nibh in lectus pellentesque at nulla suspendisse potenti
87 | 86,Sol,Iacopo,siacopo2d@hugedomains.com,Male,148.13.113.71,justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget
88 | 87,Waiter,Flemmich,wflemmich2e@archive.org,Male,119.196.69.233,odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut
89 | 88,Gayle,Korba,gkorba2f@japanpost.jp,Female,101.227.66.137,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum
90 | 89,Aeriel,Januszewski,ajanuszewski2g@europa.eu,Female,44.187.117.9,etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst
91 | 90,Frazier,Pickworth,fpickworth2h@pcworld.com,Male,192.241.214.249,posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus vitae
92 | 91,Rafi,Karolczyk,rkarolczyk2i@ca.gov,Male,58.176.232.103,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla
93 | 92,Dante,Rymell,drymell2j@cpanel.net,Male,154.34.140.144,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum mauris non ligula pellentesque
94 | 93,Darla,Feely,dfeely2k@unc.edu,Female,234.119.129.183,montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis dis parturient montes
95 | 94,Seymour,Densey,sdensey2l@51.la,Male,13.211.116.247,in tempus sit amet sem fusce consequat nulla nisl nunc
96 | 95,Alano,Blague,ablague2m@ftc.gov,Male,194.113.170.18,faucibus orci luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec nisi
97 | 96,Bartlett,Trounce,btrounce2n@bandcamp.com,Male,41.31.216.254,eleifend quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem
98 | 97,Mandel,Silliman,msilliman2o@google.com.br,Male,92.27.219.21,aenean auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit
99 | 98,Gerrard,Moxon,gmoxon2p@wikispaces.com,Male,58.246.131.46,id justo sit amet sapien dignissim vestibulum vestibulum ante ipsum primis in faucibus orci
100 | 99,Meryl,Rossey,mrossey2q@sun.com,Female,26.223.20.51,ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae duis
101 | 100,Sholom,Bengtsen,sbengtsen2r@google.co.jp,Male,39.44.28.105,cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam
102 |
--------------------------------------------------------------------------------
/just_for_fun/file_access/output/MOCK_DATA_WITH_PROJECT.csv:
--------------------------------------------------------------------------------
1 | id,first_name,last_name,email,gender,ip_address,message,project
2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor,D2
3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus,D2
4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui,D3
5 | 4,Morlee,Summerton,msummerton3@youtube.com,Male,221.95.67.170,quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie,D3
6 | 5,Adler,Steptow,asteptow4@bizjournals.com,Male,215.156.252.103,quis tortor id nulla ultrices aliquet maecenas leo odio condimentum,D3
7 | 6,Susanetta,Peach,speach5@about.com,Female,199.21.109.212,a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue vestibulum,D2
8 | 7,Waring,Rouby,wrouby6@ihg.com,Male,199.21.3.154,parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida,D3
9 | 8,Farra,Adanet,fadanet7@4shared.com,Female,11.117.37.31,sociis natoque penatibus et magnis dis parturient montes nascetur ridiculus,D1
10 | 9,Zonnya,Van,zvan8@ftc.gov,Female,66.253.168.84,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in faucibus,D3
11 | 10,Jonathan,Cherrett,jcherrett9@admin.ch,Male,28.20.34.252,laoreet ut rhoncus aliquet pulvinar sed nisl nunc rhoncus dui vel sem sed,D3
12 | 11,Ramona,Rispine,rrispinea@cnet.com,Female,149.48.48.207,in purus eu magna vulputate luctus cum sociis natoque penatibus et magnis dis parturient montes nascetur,D3
13 | 12,Bidget,Tanby,btanbyb@miitbeian.gov.cn,Bigender,86.185.76.82,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec,D3
14 | 13,Tim,Juanico,tjuanicoc@nsw.gov.au,Male,100.231.76.87,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum,D3
15 | 14,Mariann,Valentelli,mvalentellid@nature.com,Female,236.199.109.232,cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat,D2
16 | 15,Francois,Macek,fmaceke@ning.com,Male,134.86.61.194,interdum in ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia,D1
17 | 16,Lise,Stuehmeier,lstuehmeierf@narod.ru,Female,201.135.223.48,magnis dis parturient montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis,D3
18 | 17,Jule,Coley,jcoleyg@cnet.com,Male,50.18.145.153,sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie,D2
19 | 18,Shelia,Condy,scondyh@businessinsider.com,Bigender,133.163.110.102,lobortis ligula sit amet eleifend pede libero quis orci nullam molestie nibh,D3
20 | 19,Nickolas,Lurcock,nlurcocki@xing.com,Male,15.0.79.220,ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti,D1
21 | 20,Beauregard,Leving,blevingj@exblog.jp,Male,105.122.125.150,orci eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu,D1
22 | 21,Ephraim,Comini,ecominik@creativecommons.org,Male,225.164.139.15,ligula pellentesque ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at,D1
23 | 22,Serge,Warmington,swarmingtonl@a8.net,Male,31.38.85.191,molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec,D1
24 | 23,Mar,Rickman,mrickmanm@ucoz.com,Male,123.145.218.101,lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper,D3
25 | 24,Ashlan,Rycraft,arycraftn@phoca.cz,Female,27.60.25.138,sed vel enim sit amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac,D2
26 | 25,Beatrice,Antonoyev,bantonoyevo@fotki.com,Female,222.35.15.241,at feugiat non pretium quis lectus suspendisse potenti in eleifend,D1
27 | 26,Sandy,Cockshott,scockshottp@umn.edu,Female,29.121.131.207,erat eros viverra eget congue eget semper rutrum nulla nunc purus phasellus in,D2
28 | 27,Barnie,Spieck,bspieckq@ycombinator.com,Male,83.191.46.104,turpis a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D1
29 | 28,Augustin,Mildmott,amildmottr@dedecms.com,Genderqueer,22.198.173.45,rutrum rutrum neque aenean auctor gravida sem praesent id massa id nisl,D1
30 | 29,Clem,Verbeke,cverbekes@webmd.com,Male,96.55.88.58,eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in,D1
31 | 30,Leland,Oene,loenet@merriam-webster.com,Female,184.8.16.13,ligula nec sem duis aliquam convallis nunc proin at turpis a pede posuere,D1
32 | 31,Greggory,Tadman,gtadmanu@unesco.org,Male,109.228.187.124,luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet,D3
33 | 32,Tandy,Tilliard,ttilliardv@msu.edu,Polygender,169.88.229.190,integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia sapien quis,D3
34 | 33,Ondrea,Gibbens,ogibbensw@odnoklassniki.ru,Female,230.131.21.204,eleifend donec ut dolor morbi vel lectus in quam fringilla rhoncus mauris enim leo rhoncus,D1
35 | 34,Claire,Jellett,cjellettx@npr.org,Female,237.142.247.207,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu,D1
36 | 35,Patrica,Docwra,pdocwray@loc.gov,Female,57.68.189.196,volutpat quam pede lobortis ligula sit amet eleifend pede libero quis,D2
37 | 36,Ludovico,Durrand,ldurrandz@vkontakte.ru,Male,213.204.107.140,a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id,D3
38 | 37,Brandyn,Enrietto,benrietto10@reference.com,Male,71.85.30.227,in faucibus orci luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet,D1
39 | 38,Pavel,Shury,pshury11@cyberchimps.com,Male,9.122.13.127,pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat metus,D3
40 | 39,Korney,Radsdale,kradsdale12@adobe.com,Agender,11.31.223.56,mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit,D1
41 | 40,Filmer,Brugman,fbrugman13@slate.com,Male,8.194.92.208,fusce consequat nulla nisl nunc nisl duis bibendum felis sed interdum,D3
42 | 41,Artus,McQuaker,amcquaker14@europa.eu,Male,165.194.178.43,integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D2
43 | 42,Shaughn,Clarage,sclarage15@csmonitor.com,Male,133.166.203.189,proin at turpis a pede posuere nonummy integer non velit donec diam neque vestibulum,D3
44 | 43,Sal,Townrow,stownrow16@mit.edu,Male,186.233.158.243,porttitor id consequat in consequat ut nulla sed accumsan felis ut,D1
45 | 44,Laurens,Suero,lsuero17@theguardian.com,Male,91.138.55.164,libero convallis eget eleifend luctus ultricies eu nibh quisque id justo sit amet sapien dignissim,D1
46 | 45,Whitaker,Fray,wfray18@typepad.com,Male,15.202.52.204,luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec,D3
47 | 46,Lodovico,Kilmurray,lkilmurray19@pbs.org,Male,133.52.192.14,in porttitor pede justo eu massa donec dapibus duis at velit eu est congue,D1
48 | 47,Zeb,Jago,zjago1a@amazon.co.jp,Male,33.172.134.241,leo odio porttitor id consequat in consequat ut nulla sed,D3
49 | 48,Kenyon,Kembry,kkembry1b@usda.gov,Male,57.219.244.202,ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at,D2
50 | 49,Emilio,Murfill,emurfill1c@geocities.jp,Male,125.85.233.66,feugiat et eros vestibulum ac est lacinia nisi venenatis tristique fusce congue diam id ornare imperdiet sapien,D3
51 | 50,Ruggiero,McGahy,rmcgahy1d@usda.gov,Male,174.102.12.131,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in,D2
52 | 51,Lou,Mulvaney,lmulvaney1e@independent.co.uk,Female,185.156.141.80,faucibus accumsan odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut dolor morbi,D2
53 | 52,Rodie,Kopfer,rkopfer1f@thetimes.co.uk,Female,236.130.221.23,metus arcu adipiscing molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci vehicula,D1
54 | 53,Tabbatha,Headon,theadon1g@bloglovin.com,Female,29.182.214.92,ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi,D1
55 | 54,Casper,Kleinsmuntz,ckleinsmuntz1h@time.com,Non-binary,241.198.185.114,auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit amet justo morbi ut odio cras mi,D1
56 | 55,Felike,Meriott,fmeriott1i@nbcnews.com,Male,74.9.71.45,erat fermentum justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget elit sodales scelerisque mauris,D3
57 | 56,Jone,Startin,jstartin1j@go.com,Male,222.163.247.254,ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque,D2
58 | 57,Robbie,Bardwell,rbardwell1k@eventbrite.com,Female,31.32.82.2,pretium iaculis justo in hac habitasse platea dictumst etiam faucibus cursus urna ut tellus,D2
59 | 58,Valida,Fordy,vfordy1l@ebay.com,Female,200.107.191.6,duis aliquam convallis nunc proin at turpis a pede posuere nonummy integer,D3
60 | 59,Carline,Muslim,cmuslim1m@google.nl,Female,135.156.143.43,tincidunt eget tempus vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus,D2
61 | 60,Lindsy,Crampsy,lcrampsy1n@pbs.org,Female,196.28.176.125,lacus at turpis donec posuere metus vitae ipsum aliquam non mauris morbi non lectus aliquam sit amet diam,D1
62 | 61,Lorain,Daveran,ldaveran1o@tinypic.com,Female,32.161.81.252,sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer,D2
63 | 62,Joelie,Babbage,jbabbage1p@businessinsider.com,Female,40.16.148.236,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam,D3
64 | 63,Rob,Camble,rcamble1q@theguardian.com,Male,46.16.134.71,et ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus,D2
65 | 64,Pete,Butterfint,pbutterfint1r@globo.com,Male,103.180.67.203,pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet nunc viverra,D3
66 | 65,Camey,McCorrie,cmccorrie1s@scribd.com,Bigender,160.40.98.81,in congue etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst etiam faucibus,D2
67 | 66,Charlton,Rattenberie,crattenberie1t@bbc.co.uk,Genderqueer,225.201.157.166,euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis nunc proin,D3
68 | 67,Wayne,Squelch,wsquelch1u@statcounter.com,Male,34.162.46.167,tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum ac lobortis vel dapibus at diam nam,D2
69 | 68,Dusty,Orknay,dorknay1v@google.cn,Female,164.168.241.160,mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in hac habitasse platea dictumst aliquam augue quam sollicitudin,D2
70 | 69,Marietta,Henrych,mhenrych1w@posterous.com,Male,144.205.241.125,nonummy maecenas tincidunt lacus at velit vivamus vel nulla eget eros elementum pellentesque quisque porta volutpat,D2
71 | 70,Seward,Wines,swines1x@dion.ne.jp,Male,179.111.158.128,justo eu massa donec dapibus duis at velit eu est congue elementum in hac habitasse platea dictumst morbi,D2
72 | 71,Brandie,Dishmon,bdishmon1y@accuweather.com,Female,43.198.111.81,velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D1
73 | 72,Krispin,Hawkes,khawkes1z@goo.gl,Male,25.243.0.47,amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper purus sit,D2
74 | 73,Lenci,Quarrie,lquarrie20@hexun.com,Male,128.155.226.204,convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia,D1
75 | 74,Ettie,Mew,emew21@oakley.com,Female,241.248.54.155,erat curabitur gravida nisi at nibh in hac habitasse platea,D1
76 | 75,Van,Snook,vsnook22@qq.com,Male,61.219.61.202,tortor risus dapibus augue vel accumsan tellus nisi eu orci,D2
77 | 76,Olenolin,Mulroy,omulroy23@latimes.com,Male,226.135.112.198,mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a,D1
78 | 77,Annabelle,Feuell,afeuell24@miibeian.gov.cn,Female,67.132.7.234,blandit lacinia erat vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede justo lacinia eget,D1
79 | 78,Freeland,Davydenko,fdavydenko25@dmoz.org,Male,142.8.61.193,non mauris morbi non lectus aliquam sit amet diam in magna bibendum imperdiet,D2
80 | 79,Dolf,Norkett,dnorkett26@weather.com,Male,171.106.145.215,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu felis fusce posuere,D3
81 | 80,Murry,Kettridge,mkettridge27@pagesperso-orange.fr,Male,89.26.132.166,non mi integer ac neque duis bibendum morbi non quam nec,D3
82 | 81,Neill,Bockett,nbockett28@moonfruit.com,Male,178.228.106.179,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra,D1
83 | 82,Erroll,Cressy,ecressy29@uol.com.br,Male,80.2.18.106,hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci,D2
84 | 83,Yorgos,Ropcke,yropcke2a@census.gov,Male,15.186.0.137,maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet maecenas leo,D2
85 | 84,Freddy,Sirey,fsirey2b@bandcamp.com,Female,239.243.25.52,rutrum rutrum neque aenean auctor gravida sem praesent id massa id,D1
86 | 85,Irita,Tamplin,itamplin2c@tmall.com,Female,244.230.38.59,quis orci nullam molestie nibh in lectus pellentesque at nulla suspendisse potenti,D2
87 | 86,Sol,Iacopo,siacopo2d@hugedomains.com,Male,148.13.113.71,justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget,D3
88 | 87,Waiter,Flemmich,wflemmich2e@archive.org,Male,119.196.69.233,odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut,D2
89 | 88,Gayle,Korba,gkorba2f@japanpost.jp,Female,101.227.66.137,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum,D3
90 | 89,Aeriel,Januszewski,ajanuszewski2g@europa.eu,Female,44.187.117.9,etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst,D2
91 | 90,Frazier,Pickworth,fpickworth2h@pcworld.com,Male,192.241.214.249,posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus vitae,D2
92 | 91,Rafi,Karolczyk,rkarolczyk2i@ca.gov,Male,58.176.232.103,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla,D2
93 | 92,Dante,Rymell,drymell2j@cpanel.net,Male,154.34.140.144,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum mauris non ligula pellentesque,D1
94 | 93,Darla,Feely,dfeely2k@unc.edu,Female,234.119.129.183,montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis dis parturient montes,D1
95 | 94,Seymour,Densey,sdensey2l@51.la,Male,13.211.116.247,in tempus sit amet sem fusce consequat nulla nisl nunc,D3
96 | 95,Alano,Blague,ablague2m@ftc.gov,Male,194.113.170.18,faucibus orci luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec nisi,D1
97 | 96,Bartlett,Trounce,btrounce2n@bandcamp.com,Male,41.31.216.254,eleifend quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem,D1
98 | 97,Mandel,Silliman,msilliman2o@google.com.br,Male,92.27.219.21,aenean auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit,D3
99 | 98,Gerrard,Moxon,gmoxon2p@wikispaces.com,Male,58.246.131.46,id justo sit amet sapien dignissim vestibulum vestibulum ante ipsum primis in faucibus orci,D3
100 | 99,Meryl,Rossey,mrossey2q@sun.com,Female,26.223.20.51,ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae duis,D2
101 | 100,Sholom,Bengtsen,sbengtsen2r@google.co.jp,Male,39.44.28.105,cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam,D3
102 |
--------------------------------------------------------------------------------
/part_3_creating_from_csv/input/MOCK_DATA_WITH_PROJECT.csv:
--------------------------------------------------------------------------------
1 | id,first_name,last_name,email,gender,ip_address,message,project
2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor,D2
3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus,D2
4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui,D3
5 | 4,Morlee,Summerton,msummerton3@youtube.com,Male,221.95.67.170,quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie,D3
6 | 5,Adler,Steptow,asteptow4@bizjournals.com,Male,215.156.252.103,quis tortor id nulla ultrices aliquet maecenas leo odio condimentum,D3
7 | 6,Susanetta,Peach,speach5@about.com,Female,199.21.109.212,a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue vestibulum,D2
8 | 7,Waring,Rouby,wrouby6@ihg.com,Male,199.21.3.154,parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida,D3
9 | 8,Farra,Adanet,fadanet7@4shared.com,Female,11.117.37.31,sociis natoque penatibus et magnis dis parturient montes nascetur ridiculus,D1
10 | 9,Zonnya,Van,zvan8@ftc.gov,Female,66.253.168.84,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in faucibus,D3
11 | 10,Jonathan,Cherrett,jcherrett9@admin.ch,Male,28.20.34.252,laoreet ut rhoncus aliquet pulvinar sed nisl nunc rhoncus dui vel sem sed,D3
12 | 11,Ramona,Rispine,rrispinea@cnet.com,Female,149.48.48.207,in purus eu magna vulputate luctus cum sociis natoque penatibus et magnis dis parturient montes nascetur,D3
13 | 12,Bidget,Tanby,btanbyb@miitbeian.gov.cn,Bigender,86.185.76.82,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec,D3
14 | 13,Tim,Juanico,tjuanicoc@nsw.gov.au,Male,100.231.76.87,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum,D3
15 | 14,Mariann,Valentelli,mvalentellid@nature.com,Female,236.199.109.232,cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat,D2
16 | 15,Francois,Macek,fmaceke@ning.com,Male,134.86.61.194,interdum in ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia,D1
17 | 16,Lise,Stuehmeier,lstuehmeierf@narod.ru,Female,201.135.223.48,magnis dis parturient montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis,D3
18 | 17,Jule,Coley,jcoleyg@cnet.com,Male,50.18.145.153,sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie,D2
19 | 18,Shelia,Condy,scondyh@businessinsider.com,Bigender,133.163.110.102,lobortis ligula sit amet eleifend pede libero quis orci nullam molestie nibh,D3
20 | 19,Nickolas,Lurcock,nlurcocki@xing.com,Male,15.0.79.220,ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti,D1
21 | 20,Beauregard,Leving,blevingj@exblog.jp,Male,105.122.125.150,orci eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu,D1
22 | 21,Ephraim,Comini,ecominik@creativecommons.org,Male,225.164.139.15,ligula pellentesque ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at,D1
23 | 22,Serge,Warmington,swarmingtonl@a8.net,Male,31.38.85.191,molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec,D1
24 | 23,Mar,Rickman,mrickmanm@ucoz.com,Male,123.145.218.101,lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper,D3
25 | 24,Ashlan,Rycraft,arycraftn@phoca.cz,Female,27.60.25.138,sed vel enim sit amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac,D2
26 | 25,Beatrice,Antonoyev,bantonoyevo@fotki.com,Female,222.35.15.241,at feugiat non pretium quis lectus suspendisse potenti in eleifend,D1
27 | 26,Sandy,Cockshott,scockshottp@umn.edu,Female,29.121.131.207,erat eros viverra eget congue eget semper rutrum nulla nunc purus phasellus in,D2
28 | 27,Barnie,Spieck,bspieckq@ycombinator.com,Male,83.191.46.104,turpis a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D1
29 | 28,Augustin,Mildmott,amildmottr@dedecms.com,Genderqueer,22.198.173.45,rutrum rutrum neque aenean auctor gravida sem praesent id massa id nisl,D1
30 | 29,Clem,Verbeke,cverbekes@webmd.com,Male,96.55.88.58,eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in,D1
31 | 30,Leland,Oene,loenet@merriam-webster.com,Female,184.8.16.13,ligula nec sem duis aliquam convallis nunc proin at turpis a pede posuere,D1
32 | 31,Greggory,Tadman,gtadmanu@unesco.org,Male,109.228.187.124,luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet,D3
33 | 32,Tandy,Tilliard,ttilliardv@msu.edu,Polygender,169.88.229.190,integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia sapien quis,D3
34 | 33,Ondrea,Gibbens,ogibbensw@odnoklassniki.ru,Female,230.131.21.204,eleifend donec ut dolor morbi vel lectus in quam fringilla rhoncus mauris enim leo rhoncus,D1
35 | 34,Claire,Jellett,cjellettx@npr.org,Female,237.142.247.207,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu,D1
36 | 35,Patrica,Docwra,pdocwray@loc.gov,Female,57.68.189.196,volutpat quam pede lobortis ligula sit amet eleifend pede libero quis,D2
37 | 36,Ludovico,Durrand,ldurrandz@vkontakte.ru,Male,213.204.107.140,a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id,D3
38 | 37,Brandyn,Enrietto,benrietto10@reference.com,Male,71.85.30.227,in faucibus orci luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet,D1
39 | 38,Pavel,Shury,pshury11@cyberchimps.com,Male,9.122.13.127,pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat metus,D3
40 | 39,Korney,Radsdale,kradsdale12@adobe.com,Agender,11.31.223.56,mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit,D1
41 | 40,Filmer,Brugman,fbrugman13@slate.com,Male,8.194.92.208,fusce consequat nulla nisl nunc nisl duis bibendum felis sed interdum,D3
42 | 41,Artus,McQuaker,amcquaker14@europa.eu,Male,165.194.178.43,integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D2
43 | 42,Shaughn,Clarage,sclarage15@csmonitor.com,Male,133.166.203.189,proin at turpis a pede posuere nonummy integer non velit donec diam neque vestibulum,D3
44 | 43,Sal,Townrow,stownrow16@mit.edu,Male,186.233.158.243,porttitor id consequat in consequat ut nulla sed accumsan felis ut,D1
45 | 44,Laurens,Suero,lsuero17@theguardian.com,Male,91.138.55.164,libero convallis eget eleifend luctus ultricies eu nibh quisque id justo sit amet sapien dignissim,D1
46 | 45,Whitaker,Fray,wfray18@typepad.com,Male,15.202.52.204,luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec,D3
47 | 46,Lodovico,Kilmurray,lkilmurray19@pbs.org,Male,133.52.192.14,in porttitor pede justo eu massa donec dapibus duis at velit eu est congue,D1
48 | 47,Zeb,Jago,zjago1a@amazon.co.jp,Male,33.172.134.241,leo odio porttitor id consequat in consequat ut nulla sed,D3
49 | 48,Kenyon,Kembry,kkembry1b@usda.gov,Male,57.219.244.202,ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at,D2
50 | 49,Emilio,Murfill,emurfill1c@geocities.jp,Male,125.85.233.66,feugiat et eros vestibulum ac est lacinia nisi venenatis tristique fusce congue diam id ornare imperdiet sapien,D3
51 | 50,Ruggiero,McGahy,rmcgahy1d@usda.gov,Male,174.102.12.131,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in,D2
52 | 51,Lou,Mulvaney,lmulvaney1e@independent.co.uk,Female,185.156.141.80,faucibus accumsan odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut dolor morbi,D2
53 | 52,Rodie,Kopfer,rkopfer1f@thetimes.co.uk,Female,236.130.221.23,metus arcu adipiscing molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci vehicula,D1
54 | 53,Tabbatha,Headon,theadon1g@bloglovin.com,Female,29.182.214.92,ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi,D1
55 | 54,Casper,Kleinsmuntz,ckleinsmuntz1h@time.com,Non-binary,241.198.185.114,auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit amet justo morbi ut odio cras mi,D1
56 | 55,Felike,Meriott,fmeriott1i@nbcnews.com,Male,74.9.71.45,erat fermentum justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget elit sodales scelerisque mauris,D3
57 | 56,Jone,Startin,jstartin1j@go.com,Male,222.163.247.254,ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque,D2
58 | 57,Robbie,Bardwell,rbardwell1k@eventbrite.com,Female,31.32.82.2,pretium iaculis justo in hac habitasse platea dictumst etiam faucibus cursus urna ut tellus,D2
59 | 58,Valida,Fordy,vfordy1l@ebay.com,Female,200.107.191.6,duis aliquam convallis nunc proin at turpis a pede posuere nonummy integer,D3
60 | 59,Carline,Muslim,cmuslim1m@google.nl,Female,135.156.143.43,tincidunt eget tempus vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus,D2
61 | 60,Lindsy,Crampsy,lcrampsy1n@pbs.org,Female,196.28.176.125,lacus at turpis donec posuere metus vitae ipsum aliquam non mauris morbi non lectus aliquam sit amet diam,D1
62 | 61,Lorain,Daveran,ldaveran1o@tinypic.com,Female,32.161.81.252,sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer,D2
63 | 62,Joelie,Babbage,jbabbage1p@businessinsider.com,Female,40.16.148.236,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam,D3
64 | 63,Rob,Camble,rcamble1q@theguardian.com,Male,46.16.134.71,et ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus,D2
65 | 64,Pete,Butterfint,pbutterfint1r@globo.com,Male,103.180.67.203,pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet nunc viverra,D3
66 | 65,Camey,McCorrie,cmccorrie1s@scribd.com,Bigender,160.40.98.81,in congue etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst etiam faucibus,D2
67 | 66,Charlton,Rattenberie,crattenberie1t@bbc.co.uk,Genderqueer,225.201.157.166,euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis nunc proin,D3
68 | 67,Wayne,Squelch,wsquelch1u@statcounter.com,Male,34.162.46.167,tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum ac lobortis vel dapibus at diam nam,D2
69 | 68,Dusty,Orknay,dorknay1v@google.cn,Female,164.168.241.160,mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in hac habitasse platea dictumst aliquam augue quam sollicitudin,D2
70 | 69,Marietta,Henrych,mhenrych1w@posterous.com,Male,144.205.241.125,nonummy maecenas tincidunt lacus at velit vivamus vel nulla eget eros elementum pellentesque quisque porta volutpat,D2
71 | 70,Seward,Wines,swines1x@dion.ne.jp,Male,179.111.158.128,justo eu massa donec dapibus duis at velit eu est congue elementum in hac habitasse platea dictumst morbi,D2
72 | 71,Brandie,Dishmon,bdishmon1y@accuweather.com,Female,43.198.111.81,velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D1
73 | 72,Krispin,Hawkes,khawkes1z@goo.gl,Male,25.243.0.47,amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper purus sit,D2
74 | 73,Lenci,Quarrie,lquarrie20@hexun.com,Male,128.155.226.204,convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia,D1
75 | 74,Ettie,Mew,emew21@oakley.com,Female,241.248.54.155,erat curabitur gravida nisi at nibh in hac habitasse platea,D1
76 | 75,Van,Snook,vsnook22@qq.com,Male,61.219.61.202,tortor risus dapibus augue vel accumsan tellus nisi eu orci,D2
77 | 76,Olenolin,Mulroy,omulroy23@latimes.com,Male,226.135.112.198,mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a,D1
78 | 77,Annabelle,Feuell,afeuell24@miibeian.gov.cn,Female,67.132.7.234,blandit lacinia erat vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede justo lacinia eget,D1
79 | 78,Freeland,Davydenko,fdavydenko25@dmoz.org,Male,142.8.61.193,non mauris morbi non lectus aliquam sit amet diam in magna bibendum imperdiet,D2
80 | 79,Dolf,Norkett,dnorkett26@weather.com,Male,171.106.145.215,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu felis fusce posuere,D3
81 | 80,Murry,Kettridge,mkettridge27@pagesperso-orange.fr,Male,89.26.132.166,non mi integer ac neque duis bibendum morbi non quam nec,D3
82 | 81,Neill,Bockett,nbockett28@moonfruit.com,Male,178.228.106.179,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra,D1
83 | 82,Erroll,Cressy,ecressy29@uol.com.br,Male,80.2.18.106,hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci,D2
84 | 83,Yorgos,Ropcke,yropcke2a@census.gov,Male,15.186.0.137,maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet maecenas leo,D2
85 | 84,Freddy,Sirey,fsirey2b@bandcamp.com,Female,239.243.25.52,rutrum rutrum neque aenean auctor gravida sem praesent id massa id,D1
86 | 85,Irita,Tamplin,itamplin2c@tmall.com,Female,244.230.38.59,quis orci nullam molestie nibh in lectus pellentesque at nulla suspendisse potenti,D2
87 | 86,Sol,Iacopo,siacopo2d@hugedomains.com,Male,148.13.113.71,justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget,D3
88 | 87,Waiter,Flemmich,wflemmich2e@archive.org,Male,119.196.69.233,odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut,D2
89 | 88,Gayle,Korba,gkorba2f@japanpost.jp,Female,101.227.66.137,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum,D3
90 | 89,Aeriel,Januszewski,ajanuszewski2g@europa.eu,Female,44.187.117.9,etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst,D2
91 | 90,Frazier,Pickworth,fpickworth2h@pcworld.com,Male,192.241.214.249,posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus vitae,D2
92 | 91,Rafi,Karolczyk,rkarolczyk2i@ca.gov,Male,58.176.232.103,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla,D2
93 | 92,Dante,Rymell,drymell2j@cpanel.net,Male,154.34.140.144,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum mauris non ligula pellentesque,D1
94 | 93,Darla,Feely,dfeely2k@unc.edu,Female,234.119.129.183,montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis dis parturient montes,D1
95 | 94,Seymour,Densey,sdensey2l@51.la,Male,13.211.116.247,in tempus sit amet sem fusce consequat nulla nisl nunc,D3
96 | 95,Alano,Blague,ablague2m@ftc.gov,Male,194.113.170.18,faucibus orci luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec nisi,D1
97 | 96,Bartlett,Trounce,btrounce2n@bandcamp.com,Male,41.31.216.254,eleifend quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem,D1
98 | 97,Mandel,Silliman,msilliman2o@google.com.br,Male,92.27.219.21,aenean auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit,D3
99 | 98,Gerrard,Moxon,gmoxon2p@wikispaces.com,Male,58.246.131.46,id justo sit amet sapien dignissim vestibulum vestibulum ante ipsum primis in faucibus orci,D3
100 | 99,Meryl,Rossey,mrossey2q@sun.com,Female,26.223.20.51,ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae duis,D2
101 | 100,Sholom,Bengtsen,sbengtsen2r@google.co.jp,Male,39.44.28.105,cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam,D3
102 |
--------------------------------------------------------------------------------
/part_4_creating_assigning_and_emailing/input/MOCK_DATA_WITH_PROJECT.csv:
--------------------------------------------------------------------------------
1 | id,first_name,last_name,email,gender,ip_address,message,project
2 | 1,Lutero,Stearns,lstearns0@ning.com,Male,50.166.233.254,vestibulum vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae nulla dapibus dolor,D2
3 | 2,Nora,Illyes,nillyes1@harvard.edu,Female,92.150.59.96,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus,D2
4 | 3,Trista,Purton,tpurton2@bluehost.com,Female,210.64.4.237,neque duis bibendum morbi non quam nec dui luctus rutrum nulla tellus in sagittis dui,D3
5 | 4,Morlee,Summerton,msummerton3@youtube.com,Male,221.95.67.170,quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie,D3
6 | 5,Adler,Steptow,asteptow4@bizjournals.com,Male,215.156.252.103,quis tortor id nulla ultrices aliquet maecenas leo odio condimentum,D3
7 | 6,Susanetta,Peach,speach5@about.com,Female,199.21.109.212,a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue vestibulum,D2
8 | 7,Waring,Rouby,wrouby6@ihg.com,Male,199.21.3.154,parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida,D3
9 | 8,Farra,Adanet,fadanet7@4shared.com,Female,11.117.37.31,sociis natoque penatibus et magnis dis parturient montes nascetur ridiculus,D1
10 | 9,Zonnya,Van,zvan8@ftc.gov,Female,66.253.168.84,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in faucibus,D3
11 | 10,Jonathan,Cherrett,jcherrett9@admin.ch,Male,28.20.34.252,laoreet ut rhoncus aliquet pulvinar sed nisl nunc rhoncus dui vel sem sed,D3
12 | 11,Ramona,Rispine,rrispinea@cnet.com,Female,149.48.48.207,in purus eu magna vulputate luctus cum sociis natoque penatibus et magnis dis parturient montes nascetur,D3
13 | 12,Bidget,Tanby,btanbyb@miitbeian.gov.cn,Bigender,86.185.76.82,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec,D3
14 | 13,Tim,Juanico,tjuanicoc@nsw.gov.au,Male,100.231.76.87,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum,D3
15 | 14,Mariann,Valentelli,mvalentellid@nature.com,Female,236.199.109.232,cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat,D2
16 | 15,Francois,Macek,fmaceke@ning.com,Male,134.86.61.194,interdum in ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia,D1
17 | 16,Lise,Stuehmeier,lstuehmeierf@narod.ru,Female,201.135.223.48,magnis dis parturient montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis,D3
18 | 17,Jule,Coley,jcoleyg@cnet.com,Male,50.18.145.153,sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie,D2
19 | 18,Shelia,Condy,scondyh@businessinsider.com,Bigender,133.163.110.102,lobortis ligula sit amet eleifend pede libero quis orci nullam molestie nibh,D3
20 | 19,Nickolas,Lurcock,nlurcocki@xing.com,Male,15.0.79.220,ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti,D1
21 | 20,Beauregard,Leving,blevingj@exblog.jp,Male,105.122.125.150,orci eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu,D1
22 | 21,Ephraim,Comini,ecominik@creativecommons.org,Male,225.164.139.15,ligula pellentesque ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at,D1
23 | 22,Serge,Warmington,swarmingtonl@a8.net,Male,31.38.85.191,molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec,D1
24 | 23,Mar,Rickman,mrickmanm@ucoz.com,Male,123.145.218.101,lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper,D3
25 | 24,Ashlan,Rycraft,arycraftn@phoca.cz,Female,27.60.25.138,sed vel enim sit amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac,D2
26 | 25,Beatrice,Antonoyev,bantonoyevo@fotki.com,Female,222.35.15.241,at feugiat non pretium quis lectus suspendisse potenti in eleifend,D1
27 | 26,Sandy,Cockshott,scockshottp@umn.edu,Female,29.121.131.207,erat eros viverra eget congue eget semper rutrum nulla nunc purus phasellus in,D2
28 | 27,Barnie,Spieck,bspieckq@ycombinator.com,Male,83.191.46.104,turpis a pede posuere nonummy integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D1
29 | 28,Augustin,Mildmott,amildmottr@dedecms.com,Genderqueer,22.198.173.45,rutrum rutrum neque aenean auctor gravida sem praesent id massa id nisl,D1
30 | 29,Clem,Verbeke,cverbekes@webmd.com,Male,96.55.88.58,eget orci vehicula condimentum curabitur in libero ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in,D1
31 | 30,Leland,Oene,loenet@merriam-webster.com,Female,184.8.16.13,ligula nec sem duis aliquam convallis nunc proin at turpis a pede posuere,D1
32 | 31,Greggory,Tadman,gtadmanu@unesco.org,Male,109.228.187.124,luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet,D3
33 | 32,Tandy,Tilliard,ttilliardv@msu.edu,Polygender,169.88.229.190,integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia sapien quis,D3
34 | 33,Ondrea,Gibbens,ogibbensw@odnoklassniki.ru,Female,230.131.21.204,eleifend donec ut dolor morbi vel lectus in quam fringilla rhoncus mauris enim leo rhoncus,D1
35 | 34,Claire,Jellett,cjellettx@npr.org,Female,237.142.247.207,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu,D1
36 | 35,Patrica,Docwra,pdocwray@loc.gov,Female,57.68.189.196,volutpat quam pede lobortis ligula sit amet eleifend pede libero quis,D2
37 | 36,Ludovico,Durrand,ldurrandz@vkontakte.ru,Male,213.204.107.140,a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id,D3
38 | 37,Brandyn,Enrietto,benrietto10@reference.com,Male,71.85.30.227,in faucibus orci luctus et ultrices posuere cubilia curae donec pharetra magna vestibulum aliquet,D1
39 | 38,Pavel,Shury,pshury11@cyberchimps.com,Male,9.122.13.127,pede ac diam cras pellentesque volutpat dui maecenas tristique est et tempus semper est quam pharetra magna ac consequat metus,D3
40 | 39,Korney,Radsdale,kradsdale12@adobe.com,Agender,11.31.223.56,mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit,D1
41 | 40,Filmer,Brugman,fbrugman13@slate.com,Male,8.194.92.208,fusce consequat nulla nisl nunc nisl duis bibendum felis sed interdum,D3
42 | 41,Artus,McQuaker,amcquaker14@europa.eu,Male,165.194.178.43,integer non velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D2
43 | 42,Shaughn,Clarage,sclarage15@csmonitor.com,Male,133.166.203.189,proin at turpis a pede posuere nonummy integer non velit donec diam neque vestibulum,D3
44 | 43,Sal,Townrow,stownrow16@mit.edu,Male,186.233.158.243,porttitor id consequat in consequat ut nulla sed accumsan felis ut,D1
45 | 44,Laurens,Suero,lsuero17@theguardian.com,Male,91.138.55.164,libero convallis eget eleifend luctus ultricies eu nibh quisque id justo sit amet sapien dignissim,D1
46 | 45,Whitaker,Fray,wfray18@typepad.com,Male,15.202.52.204,luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec,D3
47 | 46,Lodovico,Kilmurray,lkilmurray19@pbs.org,Male,133.52.192.14,in porttitor pede justo eu massa donec dapibus duis at velit eu est congue,D1
48 | 47,Zeb,Jago,zjago1a@amazon.co.jp,Male,33.172.134.241,leo odio porttitor id consequat in consequat ut nulla sed,D3
49 | 48,Kenyon,Kembry,kkembry1b@usda.gov,Male,57.219.244.202,ultrices phasellus id sapien in sapien iaculis congue vivamus metus arcu adipiscing molestie hendrerit at,D2
50 | 49,Emilio,Murfill,emurfill1c@geocities.jp,Male,125.85.233.66,feugiat et eros vestibulum ac est lacinia nisi venenatis tristique fusce congue diam id ornare imperdiet sapien,D3
51 | 50,Ruggiero,McGahy,rmcgahy1d@usda.gov,Male,174.102.12.131,magna ac consequat metus sapien ut nunc vestibulum ante ipsum primis in,D2
52 | 51,Lou,Mulvaney,lmulvaney1e@independent.co.uk,Female,185.156.141.80,faucibus accumsan odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut dolor morbi,D2
53 | 52,Rodie,Kopfer,rkopfer1f@thetimes.co.uk,Female,236.130.221.23,metus arcu adipiscing molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci vehicula,D1
54 | 53,Tabbatha,Headon,theadon1g@bloglovin.com,Female,29.182.214.92,ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi,D1
55 | 54,Casper,Kleinsmuntz,ckleinsmuntz1h@time.com,Non-binary,241.198.185.114,auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit amet justo morbi ut odio cras mi,D1
56 | 55,Felike,Meriott,fmeriott1i@nbcnews.com,Male,74.9.71.45,erat fermentum justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget elit sodales scelerisque mauris,D3
57 | 56,Jone,Startin,jstartin1j@go.com,Male,222.163.247.254,ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra pede ac diam cras pellentesque,D2
58 | 57,Robbie,Bardwell,rbardwell1k@eventbrite.com,Female,31.32.82.2,pretium iaculis justo in hac habitasse platea dictumst etiam faucibus cursus urna ut tellus,D2
59 | 58,Valida,Fordy,vfordy1l@ebay.com,Female,200.107.191.6,duis aliquam convallis nunc proin at turpis a pede posuere nonummy integer,D3
60 | 59,Carline,Muslim,cmuslim1m@google.nl,Female,135.156.143.43,tincidunt eget tempus vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus,D2
61 | 60,Lindsy,Crampsy,lcrampsy1n@pbs.org,Female,196.28.176.125,lacus at turpis donec posuere metus vitae ipsum aliquam non mauris morbi non lectus aliquam sit amet diam,D1
62 | 61,Lorain,Daveran,ldaveran1o@tinypic.com,Female,32.161.81.252,sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer,D2
63 | 62,Joelie,Babbage,jbabbage1p@businessinsider.com,Female,40.16.148.236,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam,D3
64 | 63,Rob,Camble,rcamble1q@theguardian.com,Male,46.16.134.71,et ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus,D2
65 | 64,Pete,Butterfint,pbutterfint1r@globo.com,Male,103.180.67.203,pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet nunc viverra,D3
66 | 65,Camey,McCorrie,cmccorrie1s@scribd.com,Bigender,160.40.98.81,in congue etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst etiam faucibus,D2
67 | 66,Charlton,Rattenberie,crattenberie1t@bbc.co.uk,Genderqueer,225.201.157.166,euismod scelerisque quam turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis nunc proin,D3
68 | 67,Wayne,Squelch,wsquelch1u@statcounter.com,Male,34.162.46.167,tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum ac lobortis vel dapibus at diam nam,D2
69 | 68,Dusty,Orknay,dorknay1v@google.cn,Female,164.168.241.160,mollis molestie lorem quisque ut erat curabitur gravida nisi at nibh in hac habitasse platea dictumst aliquam augue quam sollicitudin,D2
70 | 69,Marietta,Henrych,mhenrych1w@posterous.com,Male,144.205.241.125,nonummy maecenas tincidunt lacus at velit vivamus vel nulla eget eros elementum pellentesque quisque porta volutpat,D2
71 | 70,Seward,Wines,swines1x@dion.ne.jp,Male,179.111.158.128,justo eu massa donec dapibus duis at velit eu est congue elementum in hac habitasse platea dictumst morbi,D2
72 | 71,Brandie,Dishmon,bdishmon1y@accuweather.com,Female,43.198.111.81,velit donec diam neque vestibulum eget vulputate ut ultrices vel augue,D1
73 | 72,Krispin,Hawkes,khawkes1z@goo.gl,Male,25.243.0.47,amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac tellus semper interdum mauris ullamcorper purus sit,D2
74 | 73,Lenci,Quarrie,lquarrie20@hexun.com,Male,128.155.226.204,convallis tortor risus dapibus augue vel accumsan tellus nisi eu orci mauris lacinia,D1
75 | 74,Ettie,Mew,emew21@oakley.com,Female,241.248.54.155,erat curabitur gravida nisi at nibh in hac habitasse platea,D1
76 | 75,Van,Snook,vsnook22@qq.com,Male,61.219.61.202,tortor risus dapibus augue vel accumsan tellus nisi eu orci,D2
77 | 76,Olenolin,Mulroy,omulroy23@latimes.com,Male,226.135.112.198,mauris lacinia sapien quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a,D1
78 | 77,Annabelle,Feuell,afeuell24@miibeian.gov.cn,Female,67.132.7.234,blandit lacinia erat vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede justo lacinia eget,D1
79 | 78,Freeland,Davydenko,fdavydenko25@dmoz.org,Male,142.8.61.193,non mauris morbi non lectus aliquam sit amet diam in magna bibendum imperdiet,D2
80 | 79,Dolf,Norkett,dnorkett26@weather.com,Male,171.106.145.215,in magna bibendum imperdiet nullam orci pede venenatis non sodales sed tincidunt eu felis fusce posuere,D3
81 | 80,Murry,Kettridge,mkettridge27@pagesperso-orange.fr,Male,89.26.132.166,non mi integer ac neque duis bibendum morbi non quam nec,D3
82 | 81,Neill,Bockett,nbockett28@moonfruit.com,Male,178.228.106.179,lacus morbi quis tortor id nulla ultrices aliquet maecenas leo odio condimentum id luctus nec molestie sed justo pellentesque viverra,D1
83 | 82,Erroll,Cressy,ecressy29@uol.com.br,Male,80.2.18.106,hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci eget orci,D2
84 | 83,Yorgos,Ropcke,yropcke2a@census.gov,Male,15.186.0.137,maecenas rhoncus aliquam lacus morbi quis tortor id nulla ultrices aliquet maecenas leo,D2
85 | 84,Freddy,Sirey,fsirey2b@bandcamp.com,Female,239.243.25.52,rutrum rutrum neque aenean auctor gravida sem praesent id massa id,D1
86 | 85,Irita,Tamplin,itamplin2c@tmall.com,Female,244.230.38.59,quis orci nullam molestie nibh in lectus pellentesque at nulla suspendisse potenti,D2
87 | 86,Sol,Iacopo,siacopo2d@hugedomains.com,Male,148.13.113.71,justo nec condimentum neque sapien placerat ante nulla justo aliquam quis turpis eget,D3
88 | 87,Waiter,Flemmich,wflemmich2e@archive.org,Male,119.196.69.233,odio curabitur convallis duis consequat dui nec nisi volutpat eleifend donec ut,D2
89 | 88,Gayle,Korba,gkorba2f@japanpost.jp,Female,101.227.66.137,penatibus et magnis dis parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum,D3
90 | 89,Aeriel,Januszewski,ajanuszewski2g@europa.eu,Female,44.187.117.9,etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst,D2
91 | 90,Frazier,Pickworth,fpickworth2h@pcworld.com,Male,192.241.214.249,posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus vitae,D2
92 | 91,Rafi,Karolczyk,rkarolczyk2i@ca.gov,Male,58.176.232.103,consequat morbi a ipsum integer a nibh in quis justo maecenas rhoncus aliquam lacus morbi quis tortor id nulla,D2
93 | 92,Dante,Rymell,drymell2j@cpanel.net,Male,154.34.140.144,lorem ipsum dolor sit amet consectetuer adipiscing elit proin interdum mauris non ligula pellentesque,D1
94 | 93,Darla,Feely,dfeely2k@unc.edu,Female,234.119.129.183,montes nascetur ridiculus mus vivamus vestibulum sagittis sapien cum sociis natoque penatibus et magnis dis parturient montes,D1
95 | 94,Seymour,Densey,sdensey2l@51.la,Male,13.211.116.247,in tempus sit amet sem fusce consequat nulla nisl nunc,D3
96 | 95,Alano,Blague,ablague2m@ftc.gov,Male,194.113.170.18,faucibus orci luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur convallis duis consequat dui nec nisi,D1
97 | 96,Bartlett,Trounce,btrounce2n@bandcamp.com,Male,41.31.216.254,eleifend quam a odio in hac habitasse platea dictumst maecenas ut massa quis augue luctus tincidunt nulla mollis molestie lorem,D1
98 | 97,Mandel,Silliman,msilliman2o@google.com.br,Male,92.27.219.21,aenean auctor gravida sem praesent id massa id nisl venenatis lacinia aenean sit,D3
99 | 98,Gerrard,Moxon,gmoxon2p@wikispaces.com,Male,58.246.131.46,id justo sit amet sapien dignissim vestibulum vestibulum ante ipsum primis in faucibus orci,D3
100 | 99,Meryl,Rossey,mrossey2q@sun.com,Female,26.223.20.51,ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae duis,D2
101 | 100,Sholom,Bengtsen,sbengtsen2r@google.co.jp,Male,39.44.28.105,cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam,D3
102 |
--------------------------------------------------------------------------------
/src/jirascripting/helpers.py:
--------------------------------------------------------------------------------
1 |
2 | import requests
3 | from src.jirascripting.auth_and_headers import jira_auth_and_headers
4 | import json
5 |
6 |
7 | def get_issue(this_issue_key):
8 | """Gets all fields for the epic or story queried
9 |
10 | Parameters:
11 | this_issue_key (string): issue identifier eg: D1-1
12 | Returns:
13 | Json Object: Object has all fields available set and vacant for the story/epic
14 |
15 | """
16 | auth, headers, base_url = jira_auth_and_headers()
17 | url = f"{base_url}/rest/api/3/issue/{this_issue_key}"
18 |
19 | response = requests.request(
20 | "GET",
21 | url,
22 | headers=headers,
23 | auth=auth
24 | )
25 | text_contents = json.loads(response.text)
26 | return text_contents
27 |
28 |
29 | def get_servicedesk_issue(this_issue_key):
30 | """Gets all fields for the epic or story queried
31 |
32 | Parameters:
33 | this_issue_key (string): issue identifier eg: D1-1
34 | Returns:
35 | Json Object: Object has all fields available set and vacant for the story/epic
36 |
37 | """
38 | auth, headers, base_url = jira_auth_and_headers()
39 | url = f"{base_url}/rest/servicedeskapi/request/{this_issue_key}"
40 |
41 | response = requests.request(
42 | "GET",
43 | url,
44 | headers=headers,
45 | auth=auth
46 | )
47 | text_contents = json.loads(response.text)
48 | return text_contents
49 |
50 |
51 | def get_issue_status_category(this_issue_key):
52 | """Gets all fields for the epic or story queried and returns the status category
53 |
54 | Parameters:
55 | this_issue_key (string): issue identifier eg: D1-1
56 | Returns:
57 | String: status category new, indeterminate or done
58 |
59 | """
60 | auth, headers, base_url = jira_auth_and_headers()
61 | url = f"{base_url}/rest/api/3/issue/{this_issue_key}"
62 |
63 | response = requests.request(
64 | "GET",
65 | url,
66 | headers=headers,
67 | auth=auth
68 | )
69 | issue_json = json.loads(response.text)
70 | status_category = issue_json.get('fields', {}).get('status', {}).get('statusCategory', {}).get('key', None)
71 | return status_category
72 |
73 |
74 | def get_issue_status(this_issue_key):
75 | """Gets all fields for the epic or story queried and returns the status category
76 |
77 | Parameters:
78 | this_issue_key (string): issue identifier eg: D1-1
79 | Returns:
80 | String: status category new, indeterminate or done
81 |
82 | """
83 | auth, headers, base_url = jira_auth_and_headers()
84 | url = f"{base_url}/rest/api/3/issue/{this_issue_key}"
85 |
86 | response = requests.request(
87 | "GET",
88 | url,
89 | headers=headers,
90 | auth=auth
91 | )
92 | issue_json = json.loads(response.text)
93 | status_ = issue_json.get('fields', {}).get('status', {}).get('name', None)
94 | return status_
95 |
96 |
97 | def get_single_project(this_project_id):
98 | """Gets all fields set and vacant for the epic or story queried
99 |
100 | Parameters:
101 | this_project_id (string): project identifier eg: D1
102 | Returns:
103 | Json Object: Object has all project information
104 |
105 | """
106 | auth, headers, base_url = jira_auth_and_headers()
107 |
108 | # single project
109 | url = f"{base_url}/rest/api/3/project/{this_project_id}"
110 |
111 | response = requests.request(
112 | "GET",
113 | url,
114 | headers=headers,
115 | auth=auth
116 | )
117 | json_res = json.loads(response.text)
118 | return json_res
119 |
120 |
121 | def get_all_projects():
122 | """Gets all projects in this jira instance, will return archived projects also
123 |
124 | Returns:
125 | Json Object: describes the projects n this jira instance
126 |
127 | """
128 | projects_ = []
129 | auth, headers, base_url = jira_auth_and_headers()
130 | url = f"{base_url}/rest/api/3/project/search"
131 |
132 | while url is not None:
133 | response = requests.request(
134 | "GET",
135 | url,
136 | headers=headers,
137 | auth=auth
138 | )
139 | json_res = json.loads(response.text)
140 | current_list_of_projects = json_res.get('values')
141 | for proj in current_list_of_projects:
142 | projects_.append(proj)
143 | url = json_res.get("nextPage", None)
144 |
145 | return projects_
146 |
147 |
148 | def create_epic_link(link_from, link_to, link_type):
149 | """Links epics together in a number of meaningful ways
150 | Parameters:
151 | link_from (string): epic key eg: D1-1 this is the new epic, the child
152 | link_to (string): epic key eg: D1-1 this is the uber epic, the parent
153 | link_type (string): Relates, Blocks, Cloners, Duplicate
154 | Returns:
155 | Json Object:
156 |
157 | """
158 | auth, headers, base_url = jira_auth_and_headers()
159 | url = f"{base_url}/rest/api/3/issueLink"
160 |
161 | payload = json.dumps({
162 | "outwardIssue": {
163 | "key": f"{link_from}"
164 | },
165 | "inwardIssue": {
166 | "key": f"{link_to}"
167 | },
168 | "type": {
169 | "name": f"{link_type}"
170 | }
171 | })
172 |
173 | response = requests.request(
174 | "POST",
175 | url,
176 | data=payload,
177 | headers=headers,
178 | auth=auth
179 | )
180 | text_response = "No link created"
181 | if response.ok:
182 | text_response = f"{link_from} now {link_type} {link_to}"
183 | return text_response
184 |
185 |
186 | def get_issue_assignee(this_issue_id):
187 | """Gets all stories attached to an epic
188 |
189 | Parameters:
190 | this_issue_id (string): issue identifier eg: D1-1
191 | Returns:
192 | Json Object: Object has assignee_name, assignee_email, reporter_name, reporter_email
193 |
194 | """
195 | auth, headers, base_url = jira_auth_and_headers()
196 | url = f"{base_url}/rest/api/3/issue/{this_issue_id}"
197 | response = requests.request(
198 | "GET",
199 | url,
200 | headers=headers,
201 | auth=auth
202 | )
203 |
204 | json_res = json.loads(response.text)
205 | assignee_email = json_res['fields'].get('assignee', {}).get('emailAddress', None)
206 | assignee_name = json_res['fields'].get('assignee', {}).get('displayName', None)
207 | assignee_id = json_res['fields'].get('assignee', {}).get('accountId', None)
208 | this_assignee = {"assignee_name": assignee_name, "assignee_email": assignee_email, "assignee_id": assignee_id}
209 |
210 | return this_assignee
211 |
212 |
213 | def get_stories_from_epic(epic):
214 | """Gets all stories attached to an epic
215 |
216 | Parameters: epic (string): Epic identifier eg: SECCOMPPM-93 Returns: Json Object: Key is story key, attributes:
217 | status_name, status_category, priority_name, project_name and project_key
218 |
219 | """
220 | epic_name = epic
221 | start_at = 0
222 | stories_in_epic = {}
223 | auth, headers, base_url = jira_auth_and_headers()
224 | url = f"{base_url}/rest/agile/1.0/epic/{epic_name}/issue?maxResults=50&start_at={start_at}"
225 | while url is not None:
226 | response = requests.request(
227 | "GET",
228 | url,
229 | headers=headers,
230 | auth=auth
231 | )
232 | ret_json = json.loads(response.text)
233 | total_expected_results = ret_json.get('total', 0)
234 | for this_issue in ret_json["issues"]:
235 | this_issue_key = this_issue.get("key", None)
236 | stories_in_epic[f'{this_issue_key}'] = {}
237 | stories_in_epic[f'{this_issue_key}']["status_name"] = this_issue.get(
238 | 'fields', {}).get('status', {}).get('name', None)
239 | stories_in_epic[f'{this_issue_key}']["status_category"] = this_issue.get(
240 | 'fields', {}).get('status', {}).get('statusCategory', {}).get('key', None)
241 | stories_in_epic[f'{this_issue_key}']["project_key"] = this_issue.get(
242 | 'fields', {}).get('project', {}).get('key', None)
243 | stories_in_epic[f'{this_issue_key}']["project_name"] = this_issue.get(
244 | 'fields', {}).get('project', {}).get('name', None)
245 | stories_in_epic[f'{this_issue_key}']["priority_name"] = this_issue.get(
246 | 'fields', {}).get('priority', {}).get('name', None)
247 | if len(stories_in_epic) != total_expected_results:
248 | start_at = start_at + 50
249 | url = f"{base_url}/rest/agile/1.0/epic/{epic_name}/issue?maxResults=50&start_at={start_at}"
250 | else:
251 | url = None
252 |
253 | return stories_in_epic
254 |
255 |
256 | def add_comment_to_story(this_issue_key, comment):
257 | auth, headers, base_url = jira_auth_and_headers()
258 | url = f"{base_url}/rest/api/3/issue/{this_issue_key}/comment"
259 | comment_template = {'body': {}}
260 | comment_template['body']['type'] = "doc"
261 | comment_template['body']['version'] = 1
262 | comment_template['body']['content'] = []
263 | content_parent = {"type": "paragraph", "content": []}
264 | content_child = {"text": f"{comment}", "type": "text"}
265 | content_parent['content'].append(content_child)
266 | comment_template['body']['content'].append(content_parent)
267 |
268 | payload = json.dumps(comment_template)
269 |
270 | response = requests.request(
271 | "POST",
272 | url,
273 | data=payload,
274 | headers=headers,
275 | auth=auth
276 | )
277 | return response
278 |
279 |
280 | def add_fancy_comment_to_story(this_issue_key, comment_doc):
281 | auth, headers, base_url = jira_auth_and_headers()
282 | url = f"{base_url}/rest/api/3/issue/{this_issue_key}/comment"
283 | comment_template = {'body': comment_doc}
284 | payload = json.dumps(comment_template)
285 |
286 | response = requests.request(
287 | "POST",
288 | url,
289 | data=payload,
290 | headers=headers,
291 | auth=auth
292 | )
293 | return response
294 |
295 |
296 | def get_issue_types():
297 | """Gets all issue types in this jira instance
298 |
299 | Returns:
300 | Json Object: describes the available issue types
301 |
302 | """
303 | auth, headers, base_url = jira_auth_and_headers()
304 | url = f"{base_url}/rest/api/3/issuetype"
305 |
306 | response = requests.request(
307 | "GET",
308 | url,
309 | headers=headers,
310 | auth=auth
311 | )
312 | text_contents = json.loads(response.text)
313 | return text_contents
314 |
315 |
316 | def get_priority_types():
317 | """Gets all priority types in this jira instance
318 |
319 | Returns:
320 | Json Object: describes the available priority types
321 |
322 | """
323 | auth, headers, base_url = jira_auth_and_headers()
324 | url = f"{base_url}/rest/api/3/priority"
325 |
326 | response = requests.request(
327 | "GET",
328 | url,
329 | headers=headers,
330 | auth=auth
331 | )
332 | text_contents = json.loads(response.text)
333 | return text_contents
334 |
335 |
336 | def get_all_epic_link_types():
337 | """Gets all link types in this jira instance
338 |
339 | Returns:
340 | Json Object: describes the available epic linking adjectives
341 |
342 | """
343 | auth, headers, base_url = jira_auth_and_headers()
344 | url = f"{base_url}/rest/api/3/issueLinkType"
345 |
346 | response = requests.request(
347 | "GET",
348 | url,
349 | headers=headers,
350 | auth=auth
351 | )
352 | json_res = json.loads(response.text)
353 | epic_link_types = json_res.get('issueLinkTypes')
354 |
355 | return epic_link_types
356 |
357 |
358 | def get_transitions(issue_key_):
359 | """Gets all link types in this jira instance
360 |
361 | Returns:
362 | Json Object: describes the available epic linking adjectives
363 |
364 | """
365 | auth, headers, base_url = jira_auth_and_headers()
366 | url = f"{base_url}/rest/api/3/issue/{issue_key_}/transitions"
367 |
368 | response = requests.request(
369 | "GET",
370 | url,
371 | headers=headers,
372 | auth=auth
373 | )
374 | json_res = json.loads(response.text)
375 | # epic_link_types = json_res.get('issueLinkTypes')
376 |
377 | return json_res
378 |
379 |
380 | def get_comments(issue_key_):
381 | """Gets all comments in this issue
382 |
383 | Returns:
384 | Json Object: returns all comments in json in Jira document format
385 |
386 | """
387 | auth, headers, base_url = jira_auth_and_headers()
388 | url = f"{base_url}/rest/api/3/issue/{issue_key_}/comment"
389 |
390 | response = requests.request(
391 | "GET",
392 | url,
393 | headers=headers,
394 | auth=auth
395 | )
396 | json_res = json.loads(response.text)
397 |
398 | return json_res
399 |
400 |
401 | def transition_issue(issue_key_, stage_id):
402 | """Transition issue to defined state
403 | Parameters:
404 | issue_key_ (string): issue identifier eg: D1-1
405 | stage_id (string): The integer id of the desired state of the issue (may be gathered from get_transitions)
406 | Returns:
407 | String: Response code, eg. 204
408 |
409 | """
410 | auth, headers, base_url = jira_auth_and_headers()
411 | url = f"{base_url}/rest/api/3/issue/{issue_key_}/transitions"
412 | payload = json.dumps({
413 | "transition": {
414 | "id": f"{stage_id}"
415 | },
416 | })
417 | response = requests.request(
418 | "POST",
419 | url,
420 | data=payload,
421 | headers=headers,
422 | auth=auth
423 | )
424 | status = response.status_code
425 |
426 | return f"response: {status}"
427 |
428 |
429 | def get_all_request_types(s_desk_issue_key):
430 | """Gets all comments in this issue
431 |
432 | Returns:
433 | Json Object: returns all comments in json in Jira document format
434 |
435 | """
436 | auth, headers, base_url = jira_auth_and_headers()
437 | url = f"{base_url}rest/servicedeskapi/requesttype"
438 |
439 | response = requests.request(
440 | "GET",
441 | url,
442 | headers=headers,
443 | auth=auth
444 | )
445 | json_res = json.loads(response.text)
446 | # epic_link_types = json_res.get('issueLinkTypes')
447 |
448 | return json_res
449 |
450 |
451 | if __name__ == "__main__":
452 | issue_key = "DR-49"
453 | issue = get_issue(issue_key)
454 | print(json.dumps(issue, indent=4))
455 |
456 | project_key = "D1"
457 | project = get_single_project(project_key)
458 | print(json.dumps(project, indent=4))
459 |
460 | projects = get_all_projects()
461 | print(json.dumps(projects, indent=4))
462 |
463 | # First epic key is the new one you create, the second id the one you are linking to
464 | # The third input is the type of link - get_issue_link_types.py is in the repo
465 | link_res = create_epic_link("D1-7", "D1-23", "Relates")
466 | print(link_res)
467 |
468 | get_emails = get_issue_assignee('D1-5')
469 | print(json.dumps(get_emails, indent=4))
470 |
471 | epic_name = "D1-7"
472 | issues_in_epic = get_stories_from_epic(epic_name)
473 | print(json.dumps(issues_in_epic, indent=4))
474 |
475 | story_id = "D1-7"
476 | comment_text = "I made it"
477 | res = add_comment_to_story(story_id, comment_text)
478 | print(res)
479 |
480 | story_id = "D1-7"
481 | # Build fancy comments in the same way as fancy descriptions here -
482 | # https://developer.atlassian.com/cloud/jira/platform/apis/document/playground/
483 | fancy_comment_doc = {
484 | "version": 1,
485 | "type": "doc",
486 | "content": [
487 | {
488 | "type": "paragraph",
489 | "content": [
490 | {
491 | "type": "text",
492 | "text": "this is "
493 | }
494 | ]
495 | },
496 | {
497 | "type": "paragraph",
498 | "content": [
499 | {
500 | "type": "text",
501 | "text": "some text"
502 | }
503 | ]
504 | },
505 | {
506 | "type": "paragraph",
507 | "content": [
508 | {
509 | "type": "text",
510 | "text": "and I will tag someone "
511 | },
512 | {
513 | "type": "mention",
514 | "attrs": {
515 | "id": "557058:e747a920-b560-47ee-82e3-94ffe7a59a1b",
516 | "text": "@DR",
517 | "accessLevel": ""
518 | }
519 | },
520 | {
521 | "type": "text",
522 | "text": " "
523 | }
524 | ]
525 | }
526 | ]
527 | }
528 | res = add_fancy_comment_to_story(story_id, fancy_comment_doc)
529 | print(res)
530 |
531 | issue_types = get_issue_types()
532 | print(json.dumps(issue_types, indent=4))
533 |
534 | priorities = get_priority_types()
535 | print(json.dumps(priorities, indent=4))
536 |
537 | issue_links = get_all_epic_link_types()
538 | print(json.dumps(issue_links, indent=4))
539 |
540 | comments_in_issue = get_comments(story_id)
541 | print(json.dumps(comments_in_issue, indent=4))
542 |
543 | transitions = get_transitions(issue_key)
544 | print(json.dumps(transitions, indent=4))
545 |
546 | transition_this_issue = transition_issue(issue_key, "31")
547 | print(transition_this_issue)
548 |
549 | story_id = "D1-7"
550 | issue_status_category = get_issue_status_category(story_id)
551 |
552 | story_id = "D1-7"
553 | issue_status = get_issue_status(story_id)
554 |
--------------------------------------------------------------------------------