Jira Python - all issues from all projects - python

I have some code to connect to my company’s instance of the JIRA server via Jira’s Python Client. When i do a count on all the projects available in the server, I see close to 4300 projects, but when I loop through the projects to get a list of all the issues in all the projects, I cannot get more than 149 projects. There are about 100 issues in each project so I’d expect a total of 4300 projects and 430000 issues.
But I’m getting 149 projects and the loop exists with ~27000 issues. Has anyone faced this problem? Here’s the code I’m using:
import jira.client
from jira.client import JIRA
import re
import pandas as pd
options = {"server": "https://horizon.xxxxxx.com/issues",'verify':False}
jira = JIRA(options, basic_auth=('user','pwd'))
projects = jira.projects()
allissues = []
allprojects=[]
block_size=50
for projectA in projects:
block_num=0
while True:
start_idx=block_num*block_size
issues=jira.search_issues(f'project = {projectA.key}', start_idx, block_size)
if len(issues)== 0:
break
block_num+=1
for issue in issues:
allissues.append(issue)
allprojects.append(projectA.key)

I don't the setup to currently validate my code, but the code flow should be looking like this,
First import all your necessary libraries and get all the projects, then
projectsList=[]
issuesList=[]
for proj in projects:
while true:
startIndex=block_num*block_size
issues=jira.search_issues(f'project = {projectA.key}', start_idx
if len(issues)== 0:
break
block_num+=1
issueList.extend(issues)
projectsList.append(proj)
Few pointers:
1. Block size is not needed in search issues as argument because by default value is already set at 50.
2. You don't have to add project name every time you loop your issue
If you there are still issues with the results, then do provide any additional information such as any error info, debug logs (add some print statements) etc., that might help in helping you.

Adding quotes to the projects below solved:
import jira.client
from jira.client import JIRA
import re
import pandas as pd
options = {"server": "https://horizon.xxxxxxx.com/issues2",'verify':False}
jira = JIRA(options, basic_auth=('user','pwd'))
issues2=pd.DataFrame()
projects = jira.projects()
block_size=50
for projectA in projects:
block_num=0
while True:
start_idx=block_num*block_size
issues=jira.search_issues(f'project = "{projectA.key}"', start_idx, block_size)
if len(issues)== 0:
break
block_num+=1
allissues = []
allissues.extend(issues)
for allissue in allissues:
d={
'projectname': projectA.key,
'key':allissue .key,
'assignee':allissue .fields.assignee,
'creator':allissue .fields.creator,
'reporter':allissue .fields.reporter,
'created':allissue .fields.created,
'components':allissue .fields.components,
'description':allissue .fields.description,
'summary':allissue .fields.summary,
'fixVersion':allissue .fields.fixVersions,
'subtask':allissue .fields.issuetype.name,
'priority':allissue .fields.priority.name,
'resolution':allissue .fields.resolution,
'resolution.date':allissue .fields.resolutiondate,
'status.name':allissue .fields.status.name,
'statusdescription':allissue .fields.status.description,
'updated':allissue .fields.updated,
'versions':allissue .fields.versions,
'watches':allissue .fields.watches,
'storypoints':allissue .fields.customfield_10002
}
issues2=issues2.append(d, ignore_index=True)
issues2.head()

Does your user have Browse Permission on all the projects?
Are there Issue Security Schemes not allowing you to see some issues?

Related

Can't connect to Neo4j Aura with Neomodel

I'm trying to start a project using Neo4j Aura and neomodel. I've found this post and set up my connection as suggested, however when I try to run my project I get the following error:
ValueError: Expecting url format: bolt://user:password#localhost:7687 got neo4j+s://myuser:mypass#mydb.databases.neo4j.io
I've checked the neomodel code and it specifically checks for the bolt protocol and won't continue with the neo4j+s protocol. This differs from what is suggested in the post I linked - am I missing something? I would greatly appreciate a hint in the right direction.
Here is the example code I'm trying to run:
import os
from neomodel import (config, StructuredNode, StringProperty, IntegerProperty,
UniqueIdProperty, RelationshipTo)
from dotenv import load_dotenv
if __name__ == '__main__':
load_dotenv()
user = os.environ['NEO4J_USERNAME']
psw = os.environ['NEO4J_PASSWORD']
uri = os.environ['NEO4J_URI']
config.DATABASE_URL = 'neo4j+s://{}:{}#{}'.format(user, psw, uri)
class Country(StructuredNode):
code = StringProperty(unique_index=True, required=True)
class Person(StructuredNode):
uid = UniqueIdProperty()
name = StringProperty(unique_index=True)
age = IntegerProperty(index=True, default=0)
# traverse outgoing IS_FROM relations, inflate to Country objects
country = RelationshipTo(Country, 'IS_FROM')
jim = Person(name='Jim', age=3).save() # Create
jim.age = 4
jim.save() # Update, (with validation)
Please advise your neo4j version and neo4j driver version. Bolt protocol is previously used in neo4j drivers 1.7 while neo4j protocol is for neo4j version 4.x. This protocol neo4j+s is equivalent to bolt+routing in older version. Then, I tried your code and it is working well. Notice the db aura uri at the bottom of the image.
To check your neo4j versions, open a terminal and type "pip freeze | grep neo4j".
This is my driver version:
neo4j==4.4.5
neo4j-driver==4.3.6
neomodel==4.0.8
Result:

With Python Kubernetes client, how to replicate `kubectl create -f` generally?

My Bash script using kubectl create/apply -f ... to deploy lots of Kubernetes resources has grown too large for Bash. I'm converting it to Python using the PyPI kubernetes package.
Is there a generic way to create resources given the YAML manifest? Otherwise, the only way I can see to do it would be to create and maintain a mapping from Kind to API method create_namespaced_<kind>. That seems tedious and error prone to me.
Update: I'm deploying many (10-20) resources to many (10+) GKE clusters.
Update in the year 2020, for anyone still interested in this (since the docs for the python library is mostly empty).
At the end of 2018 this pull request has been merged,
so it's now possible to do:
from kubernetes import client, config
from kubernetes import utils
config.load_kube_config()
api = client.ApiClient()
file_path = ... # A path to a deployment file
namespace = 'default'
utils.create_from_yaml(api, file_path, namespace=namespace)
EDIT: from a request in a comment, a snippet for skipping the python error if the deployment already exists
from kubernetes import client, config
from kubernetes import utils
config.load_kube_config()
api = client.ApiClient()
def skip_if_already_exists(e):
import json
# found in https://github.com/kubernetes-client/python/blob/master/kubernetes/utils/create_from_yaml.py#L165
info = json.loads(e.api_exceptions[0].body)
if info.get('reason').lower() == 'alreadyexists':
pass
else
raise e
file_path = ... # A path to a deployment file
namespace = 'default'
try:
utils.create_from_yaml(api, file_path, namespace=namespace)
except utils.FailToCreateError as e:
skip_if_already_exists(e)
I have written a following piece of code to achieve the functionality of creating k8s resources from its json/yaml file:
def create_from_yaml(yaml_file):
"""
:param yaml_file:
:return:
"""
yaml_object = yaml.loads(common.load_file(yaml_file))
group, _, version = yaml_object["apiVersion"].partition("/")
if version == "":
version = group
group = "core"
group = "".join(group.split(".k8s.io,1"))
func_to_call = "{0}{1}Api".format(group.capitalize(), version.capitalize())
k8s_api = getattr(client, func_to_call)()
kind = yaml_object["kind"]
kind = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', kind)
kind = re.sub('([a-z0-9])([A-Z])', r'\1_\2', kind).lower()
if "namespace" in yaml_object["metadata"]:
namespace = yaml_object["metadata"]["namespace"]
else:
namespace = "default"
try:
if hasattr(k8s_api, "create_namespaced_{0}".format(kind)):
resp = getattr(k8s_api, "create_namespaced_{0}".format(kind))(
body=yaml_object, namespace=namespace)
else:
resp = getattr(k8s_api, "create_{0}".format(kind))(
body=yaml_object)
except Exception as e:
raise e
print("{0} created. status='{1}'".format(kind, str(resp.status)))
return k8s_api
In above function, If you provide any object yaml/json file, it will automatically pick up the API type and object type and create the object like statefulset, deployment, service etc.
PS: The above code doesn't handler multiple kubernetes resources in one file, so you should have only one object per yaml file.
I see what you are looking for. This is possible with other k8s clients available in other languages. Here is an example in java. Unfortunately the python client library does not support that functionality yet. I opened a new feature request requesting the same and you can either choose to track it or contribute yourself :). Here is the link for the issue on GitHub.
The other way to still do what you are trying to do is to use java/golang client and put your code in a docker container.

Batch posting on blogger using gdata python client

I'm trying to copy all my Livejournal posts to my new blog on blogger.com. I do so by using slightly modified example that ships with the gdata python client. I have a json file with all of my posts imported from Livejournal. Issue is that blogger.com has a daily limit for posting new blog entries per day — 50, so you can imagine that 1300+ posts I have will be copied in a month, since I can't programmatically enter captcha after 50 imports.
I recently learned that there's also batch operation mode somewhere in gdata, but I couldn't figure how to use it. Googling didn't really help.
Any advice or help will be highly appreciated.
Thanks.
Update
Just in case, I use the following code
#!/usr/local/bin/python
import json
import requests
from gdata import service
import gdata
import atom
import getopt
import sys
from datetime import datetime as dt
from datetime import timedelta as td
from datetime import tzinfo as tz
import time
allEntries = json.load(open("todays_copy.json", "r"))
class TZ(tz):
def utcoffset(self, dt): return td(hours=-6)
class BloggerExample:
def __init__(self, email, password):
# Authenticate using ClientLogin.
self.service = service.GDataService(email, password)
self.service.source = "Blogger_Python_Sample-1.0"
self.service.service = "blogger"
self.service.server = "www.blogger.com"
self.service.ProgrammaticLogin()
# Get the blog ID for the first blog.
feed = self.service.Get("/feeds/default/blogs")
self_link = feed.entry[0].GetSelfLink()
if self_link:
self.blog_id = self_link.href.split("/")[-1]
def CreatePost(self, title, content, author_name, label, time):
LABEL_SCHEME = "http://www.blogger.com/atom/ns#"
# Create the entry to insert.
entry = gdata.GDataEntry()
entry.author.append(atom.Author(atom.Name(text=author_name)))
entry.title = atom.Title(title_type="xhtml", text=title)
entry.content = atom.Content(content_type="html", text=content)
entry.published = atom.Published(time)
entry.category.append(atom.Category(scheme=LABEL_SCHEME, term=label))
# Ask the service to insert the new entry.
return self.service.Post(entry,
"/feeds/" + self.blog_id + "/posts/default")
def run(self, data):
for year in allEntries:
for month in year["yearlydata"]:
for day in month["monthlydata"]:
for entry in day["daylydata"]:
# print year["year"], month["month"], day["day"], entry["title"].encode("utf-8")
atime = dt.strptime(entry["time"], "%I:%M %p")
hr = atime.hour
mn = atime.minute
ptime = dt(year["year"], int(month["month"]), int(day["day"]), hr, mn, 0, tzinfo=TZ()).isoformat("T")
public_post = self.CreatePost(entry["title"],
entry["content"],
"My name",
",".join(entry["tags"]),
ptime)
print "%s, %s - published, Waiting 30 minutes" % (ptime, entry["title"].encode("utf-8"))
time.sleep(30*60)
def main(data):
email = "my#email.com"
password = "MyPassW0rd"
sample = BloggerExample(email, password)
sample.run(data)
if __name__ == "__main__":
main(allEntries)
I would recommend using Google Blog converters instead ( https://code.google.com/archive/p/google-blog-converters-appengine/ )
To get started you will have to go through
https://github.com/google/gdata-python-client/blob/master/INSTALL.txt - Steps for setting up Google GData API
https://github.com/pra85/google-blog-converters-appengine/blob/master/README.txt - Steps for using Blog Convertors
Once you have everything setup , you would have to run the following command (its the LiveJournal Username and password)
livejournal2blogger.sh -u <username> -p <password> [-s <server>]
Redirect its output into a .xml file. This file can now be imported into a Blogger blog directly by going to Blogger Dashboard , your blog > Settings > Other > Blog tools > Import Blog
Here remember to check the Automatically publish all imported posts and pages option. I have tried this once before with a blog with over 400 posts and Blogger did successfully import & published them without issue
Incase you have doubts the Blogger might have some issues (because the number of posts is quite high) or you have other Blogger blogs in your account. Then just for precaution sake , create a separate Blogger (Google) account and then try importing the posts. After that you can transfer the admin controls to your real Blogger account (To transfer , you will first have to send an author invite , then raise your real Blogger account to admin level and lastly remove the dummy account. Option for sending invite is present at Settings > Basic > Permissions > Blog Authors )
Also make sure that you are using Python 2.5 otherwise these scripts will not run. Before running livejournal2blogger.sh , change the following line (Thanks for Michael Fleet for this fix http://michael.f1337.us/2011/12/28/google-blog-converters-blogger2wordpress/ )
PYTHONPATH=${PROJ_DIR}/lib python ${PROJ_DIR}/src/livejournal2blogger/lj2b.py $*
to
PYTHONPATH=${PROJ_DIR}/lib python2.5 ${PROJ_DIR}/src/livejournal2blogger/lj2b.py $*
P.S. I am aware this is not the answer to your question but as the objective of this answer is same as your question (To import more than 50 posts in a day) , Thats why I shared it. I don't have much knowledge of Python or GData API , I setup the environment & followed these steps to answer this question (And I was able to import posts from LiveJournal to Blogger with it ).
# build feed
request_feed = gdata.base.GBaseItemFeed(atom_id=atom.Id(text='test batch'))
# format each object
entry1 = gdata.base.GBaseItemFromString('--XML for your new item goes here--')
entry1.title.text = 'first batch request item'
entry2 = gdata.base.GBaseItemFromString('--XML for your new item here--')
entry2.title.text = 'second batch request item'
# Add each blog item to the request feed
request_feed.AddInsert(entry1)
request_feed.AddInsert(entry2)
# Execute the batch processes through the request_feed (all items)
result_feed = gd_client.ExecuteBatch(request_feed)

Exporting a zope folder with python

We have two zope servers running our company's internal site. One is the live site and one is the dev site. I'm working on writing a python script that moves everything from the dev server to the live server. Right now the process involves a bunch of steps that are done in the zope management interface. I need to make all that automatic so that running one script handles it all. One thing I need to do is export one folder from the live server so that I can reimport it back into the live site after the update. How can I do this from a python script?
We're using Zope 2.8 and python 2.3.4
You can try to use the functions manage_exportObject and manage_importObject located in the file $ZOPE_HOME/lib/python/OFS/ObjectManager.py
Let say we install two Zope 2.8 instances located at:
/tmp/instance/dev for the development server (port 8080)
/tmp/instance/prod for the production server (port 9090)
In the ZMI of the development server, I have created two folders /MyFolder1 and /MyFolder2 containing some page templates. The following Python script exports each folder in .zexp files, and imports them in the ZMI of the production instance:
#!/usr/bin/python
import urllib
import shutil
ids_to_transfer = ['MyFolder1', 'MyFolder2']
for id in ids_to_transfer:
urllib.urlopen('http://admin:password_dev#localhost:8080/manage_exportObject?id=' + id)
shutil.move('/tmp/instance/dev/var/' + id + '.zexp', '/tmp/instance/prod/import/' + id + '.zexp')
urllib.urlopen('http://admin:password_prod#localhost:9090/manage_delObjects?ids=' + id)
urllib.urlopen('http://admin:password_prod#localhost:9090/manage_importObject?file=' + id + '.zexp')
To make this more general and allow copying folders not in the root directory I would do something like this:
#!/usr/bin/python
import urllib
import shutil
username_dev = 'admin'
username_prod = 'admin'
password_dev = 'password_dev'
password_prod = 'password_prod'
url_dev = 'localhost:8080'
url_prod = 'localhost:9090'
paths_and_ids_to_transfer = [('level1/level2/','MyFolder1'), ('level1/','MyFolder2')]
for path, id in ids_to_transfer:
urllib.urlopen('http://%s:%s#%s/%smanage_exportObject?id=%s' % (username_dev, password_dev, url_dev, path, id))
shutil.move('/tmp/instance/dev/var/' + id + '.zexp', '/tmp/instance/prod/import/' + id + '.zexp')
urllib.urlopen('http://%s:%s#%s/%smanage_delObjects?ids=%s' % (username_prod, password_prod, url_prod, path, id))
urllib.urlopen('http://%s:%s#%s/%smanage_importObject?file=%s.zexp' % (username_prod, password_prod, url_prod, path, id))
If I had the rep I would add this to the other answer but alas...
If someone wants to merge them, please go ahead.
If you really move everything you could probably just move the Data.fs instead. But otherwise the import/export above is a good way.

Google Analytics and Python

I'm brand new at Python and I'm trying to write an extension to an app that imports GA information and parses it into MySQL. There is a shamfully sparse amount of infomation on the topic. The Google Docs only seem to have examples in JS and Java...
...I have gotten to the point where my user can authenticate into GA using SubAuth. That code is here:
import gdata.service
import gdata.analytics
from django import http
from django import shortcuts
from django.shortcuts import render_to_response
def authorize(request):
next = 'http://localhost:8000/authconfirm'
scope = 'https://www.google.com/analytics/feeds'
secure = False # set secure=True to request secure AuthSub tokens
session = False
auth_sub_url = gdata.service.GenerateAuthSubRequestUrl(next, scope, secure=secure, session=session)
return http.HttpResponseRedirect(auth_sub_url)
So, step next is getting at the data. I have found this library: (beware, UI is offensive) http://gdata-python-client.googlecode.com/svn/trunk/pydocs/gdata.analytics.html
However, I have found it difficult to navigate. It seems like I should be gdata.analytics.AnalyticsDataEntry.getDataEntry(), but I'm not sure what it is asking me to pass it.
I would love a push in the right direction. I feel I've exhausted google looking for a working example.
Thank you!!
EDIT: I have gotten farther, but my problem still isn't solved. The below method returns data (I believe).... the error I get is: "'str' object has no attribute '_BecomeChildElement'" I believe I am returning a feed? However, I don't know how to drill into it. Is there a way for me to inspect this object?
def auth_confirm(request):
gdata_service = gdata.service.GDataService('iSample_acctSample_v1.0')
feedUri='https://www.google.com/analytics/feeds/accounts/default?max-results=50'
# request feed
feed = gdata.analytics.AnalyticsDataFeed(feedUri)
print str(feed)
Maybe this post can help out. Seems like there are not Analytics specific bindings yet, so you are working with the generic gdata.
I've been using GA for a little over a year now and since about April 2009, i have used python bindings supplied in a package called python-googleanalytics by Clint Ecker et al. So far, it works quite well.
Here's where to get it: http://github.com/clintecker/python-googleanalytics.
Install it the usual way.
To use it: First, so that you don't have to manually pass in your login credentials each time you access the API, put them in a config file like so:
[Credentials]
google_account_email = youraccount#gmail.com
google_account_password = yourpassword
Name this file '.pythongoogleanalytics' and put it in your home directory.
And from an interactive prompt type:
from googleanalytics import Connection
import datetime
connection = Connection() # pass in id & pw as strings **if** not in config file
account = connection.get_account(<*your GA profile ID goes here*>)
start_date = datetime.date(2009, 12, 01)
end_data = datetime.date(2009, 12, 13)
# account object does the work, specify what data you want w/
# 'metrics' & 'dimensions'; see 'USAGE.md' file for examples
account.get_data(start_date=start_date, end_date=end_date, metrics=['visits'])
The 'get_account' method will return a python list (in above instance, bound to the variable 'account'), which contains your data.
You need 3 files within the app. client_secrets.json, analytics.dat and google_auth.py.
Create a module Query.py within the app:
class Query(object):
def __init__(self, startdate, enddate, filter, metrics):
self.startdate = startdate.strftime('%Y-%m-%d')
self.enddate = enddate.strftime('%Y-%m-%d')
self.filter = "ga:medium=" + filter
self.metrics = metrics
Example models.py: #has the following function
import google_auth
service = googleauth.initialize_service()
def total_visit(self):
object = AnalyticsData.objects.get(utm_source=self.utm_source)
trial = Query(object.date.startdate, object.date.enddate, object.utm_source, ga:sessions")
result = service.data().ga().get(ids = 'ga:<your-profile-id>', start_date = trial.startdate, end_date = trial.enddate, filters= trial.filter, metrics = trial.metrics).execute()
total_visit = result.get('rows')
<yr save command, ColumnName.object.create(data=total_visit) goes here>

Categories

Resources