How to see what can be set/updated on an issue? - python

I'm trying to use the JIRA Python API to create and update issues on different projects.
Currently I'm after timetracking but I've seen other fields that cannot be set on this or that project getting the error message:
... cannot be set. It is not on the appropriate screen, or unknown.
I can already set timetracking on some projects like:
issue.update(fields={'timetracking': {'originalEstimate': '4h'}})
But on others I get the mentioned error message although the field is clearly present among the issue fields:
>>> issue.fields.timetracking
<JIRA TimeTracking at 2072336111640>
There seems to be nothing obvious on the object itself that could make me identify the thing as "not set-able".
Here is a post on how to get the fields on the screen via REST API. I think that's what the Python thing is doing in the background. But do I really need to go that way?

Given the path from the REST API question answer we can get the data with the private _get_json:
path = 'issue/createmeta?projectKeys={KEY}&expand=projects.issuetypes.fields'
data = jira_connection._get_json(_FIELDS_PATH.format(KEY=project_key))
project_fields = {}
for issuetype in data['projects'][0]['issuetypes']:
project_fields[issuetype['name']] = dict((f, v['name']) for f,v in issuetype['fields'].items())
This will result in a project_fields dictionary like:
{
"ISSUE_TYPE_NAME": {
"FIELD_ID": "FIELD_NAME",
...
}, // for example:
"Task": {
"summary": "Summary",
"issuetype": "Issue Type",
...
}
}
As long as there is no such feature in the jira package directly.

Related

How do I verify the validity of a JSON Schema file?

I have a JSON Schema file like this one, which contains a couple of intentional bugs:
{
"$schema": "http://json-schema.org/schema#",
"type": "object",
"description": "MWE for JSON Schema Validation",
"properties": {
"valid_prop": {
"type": ["string", "number"],
"description": "This can be either a string or a number."
},
"invalid_prop": {
// NOTE: "type:" here should have been "type" (without the colon)
"type:": ["string", "null"],
"description": "Note the extra colon in the name of the type property above"
}
},
// NOTE: Reference to a non-existent property
"required": ["valid_prop", "nonexistent_prop"]
}
I'd like to write a Python script (or, even better, install a CLI with PiP) that can find those bugs.
I've seen this answer, which suggests doing the following (modified for my use case):
import json
from jsonschema import Draft4Validator
with open('./my-schema.json') as schemaf:
schema = json.loads('\n'.join(schemaf.readlines()))
Draft4Validator.check_schema(my_schema)
print("OK!") # on invalid schema we don't get here
but the above script doesn't detect either of the errors in the schema file. I would have suspected it to detect at least the extra colon in the "type:" property.
Am I using the library incorrectly? How do I write a validation script that detects this error?
You say the schema is invalid, but that isn't the case with the example you've provided.
Unknown keywords are ignored. This is to allow for extensions to be created. If unknown keywords were prevented, we wouldn't have the ecosystem of extensions that various people and groups have created, like form generation.
You say that the value in required is a "Reference to a non-existent property". The required keyword has no link to the properties keyword.
required determins which keys an object must have.
properties determines how a subschema should be applied to values in an object.
There's no need for values in required to also be included in properties. In fact it's common that they do not when building complex modular schemas.
In terms of validating if a schema is valid, you can use the JSON Schema meta schema.
In terms of checking for additional things that you consider non desireable, that's down to you, given the examples you've provided are valid.
Some libraries may provide a sanity check, but such is unlikely to pick up on the examples you've provided, as they aren't errors.

Best practice for collections in jsons: array vs dict/map

I need to pass data in a python back-end to a front end through an api call, using a json format. In the python back end, the data is in a dictionary structure, which I can easily and directly convert to a json. But should I?
My front-end developer believes the answer is no, for reasons related to best practice.
But I challenge that:
Is the best to structure a json as it is in python, or should it rather be converted to some other form, such as several arrays (as would be necessary in my example case below)?
Or, differently put:
What should be the governing principles related to collections/dicts/maps/arrays for interfacing information through jsons?
I've done some googling for an answer, but I've not come across much that addresses this directly. Links would be appreciated.
(Note about the example below: of course if the data is written to a database, it would probably make most sense for the front-end to access the database directly, but let's assume this is not the case)
Example:
In the back end there is a collection of objects called pets:
each item in the collection has a unique pet_id, some non-optional properties, e.g. name and date_of_birth, some optional properties registration_certificate_nr, adopted_from_kennel, some lists like siblings and children and some objects like medication.
Assuming that the front end needs all of this info at some point, it could be
{
"pets": {
"17-01-24-01": {
"name": "Buster",
"date_of_birth": "04/01/2017",
"registration_certificate_nr": "AAD-1123-1432"
},
"17-03-04-01": {
"name": "Hooch",
"date_of_birth": "05/02/2015",
"adopted_from_kennel": "Pretoria Shire",
"children": [
"17-05-01-01",
"17-05-01-02",
"17-05-01-03"
]
},
"17-05-01-01": {
"name": "Snappy",
"date_of_birth": "17-05-01",
"siblings": [
"17-05-01-02",
"17-05-01-03"
]
},
"17-05-01-02": {
"name": "Gizmo",
"date_of_birth": "17-05-01",
"siblings": [
"17-05-01-01",
"17-05-01-03"
]
},
"17-05-01-03": {
"name": "Toothless",
"date_of_birth": "17-05-01",
"siblings": [
"17-05-01-01",
"17-05-01-03"
],
"medication": [
{
"name": "anti-worm",
"code": "aw445",
"dosage": "1 pill per day"
},
{
"name": "disinfectant",
"code": "pdi-2",
"dosage": "as required"
}
]
}
}
}
JSON formatting is a somewhat subjective matter, and related disagreements are usually best settled between colleagues.
That being said, there are some potentially valid criticisms to be made against the JSON format in the question, especially if we are trying to create a consistent, RESTful API.
The 2 pain points that stand out:
A map collection is represented in JSON, which isn't really JSON standard compliant, or particularly RESTful.
None of the pet objects have an id defined. There is a pet_id mentioned in the question, but it seems to be maintained separately from the pet object itself. If a value is accessed in the pets map in the question, a user of the API would have to manually add the pet_id to the provided pet object in order to have the id available further down the line, when the full JSON may no longer be available.
The closest things we have to guiding standards in this situation is the REST architectural style and the JSON standard.
We can start by looking at the JSON standard. Here is a quote from the JSON wiki:
JavaScript syntax defines several native data types that are not included in the JSON standard: Map, Set, Date, Error, Regular Expression, Function, Promise, and undefined.
The key takeaway here is that JSON is not meant to represent the map data type. Python dictionaries are a map implementation, so directly serializing a dictionary to JSON with the intent to represent a map-like collection goes against the intended use of JSON.
For an individual object like a pet, the JSON object is appropriate, but for collections there is one option: the JSON array. There is a usage example with the JSON array further down in this answer.
There may be edge cases where deviating from the standard makes sense, but I don't see a reason in this scenario.
There are also some shortcomings in the JSON format from a RESTful design perspective. RESTful API design is nice because it encourages one to keep things simple and consistent. It also happens to be a de facto industry standard.
In a RESTful HTTP API, this is how fetching a single pet resource should look:
Request: GET /api/pets/17-01-24-01
Response: 200 {
"id": "17-01-24-01",
"name": "Buster",
"date_of_birth": "04/01/2017",
"registration_certificate_nr": "AAD-1123-1432"
}
The response is a completely defined resource with an explicitly defined id. It is also the simplest complete JSON representation of a pet.
Next, we define what fetching multiple pet resources looks like, assuming only 2 pets are defined:
Request: GET /api/pets
Response: 200 [
{
"id": "17-01-24-01",
"name": "Buster",
"date_of_birth": "04/01/2017",
"registration_certificate_nr": "AAD-1123-1432"
},
{
"id": "17-03-04-01",
"name": "Hooch",
"date_of_birth": "05/02/2015",
"adopted_from_kennel": "Pretoria Shire",
"children": [
"17-05-01-01",
"17-05-01-02",
"17-05-01-03"
]
}
]
The above response format is the most straight forward way to pluralize the single resource response format, thus keeping the API as simple and consistent as possible. (for the sake of brevity, I only used 2 of the sample resources from the question). Once again, the ids are explicitly defined, and belong to their respective pet objects.
Nothing is gained from adding map keys to the above format.
Proponents of the JSON format in the question may suggest to just add the id field into each pet object in order to work around pain point 2, but that would raise the question of repeating data within the response. Why does the id need to be both inside and outside the object? Surely it should only be on the inside? After eliminating the redundant data, the result will look like the response above.
That is the REST argument. There are use cases where REST doesn't really work, but this is far from that.
PS. Front ends should never access databases directly. The API is responsible for writing to and reading from whatever data persistence infrastructure is used. In a lot of bigger real world systems, there is even an additional BFF layer between the front end and the API(s), separating the front end and the DB even further.

Add a validator to a Mongodb collection with pymongo

I am trying to add a validator to a MongoDB collection using pymongo.
The command I would like to run adapted from here
Is equivalent to this:
db.runCommand( {
collMod: "contacts",
validator: { phone: { $type: 'string' } },
validationLevel: "moderate"
} )
{ "ok" : 1 }
And subsequently will throw an error if a non-string datatype is inserted tin the phone field
Using python I did the following:
db.command({'collMod': 'contacts',
'validator': {'phone': {'$type': 'string'}},
'validationLevel': 'moderate'})
.
.
.
InvalidDocument: Cannot encode object: Collection(Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'test_table'), 'contacts')
I'm sure that my python interpretation is wrong, that much is clear, however I have not been able to find the correct translation, or whether this is even possible in python
I eventually found the solution here. Hopefully it can help someone else.
Of course, when all else fails read the docs...
.. note:: the order of keys in the command document is
significant (the "verb" must come first), so commands
which require multiple keys (e.g. findandmodify)
should use an instance of :class:~bson.son.SON or
a string and kwargs instead of a Python dict
Also valid is an OrderedDict
query = [('collMod', 'contacts'),
('validator', {'phone': {'$type': 'string'}}),
('validationLevel', 'moderate')]
query = OrderedDict(query)
db.command(query)
{'ok': 1.0}
EDIT:
Current Documentation from where the above comes from. Note this was added after the question was originally answered so the documentation has changed, however it should still be relevant

OR condition in motor python

Hi I am experimenting with python and mongodb with tornado framework. I am having entry module where user can insert the data of students in academic and sports field. In mongodb terminal I did search with
db.student.find( { $or: [ { "academy": name }, { "sports": name } ] } )
but when I try to do the same with python along with MOTOR driver I end up with error.
My python command is
doc = yield db.student.find_one({ $or: [{"academy": name}, {"sports": name}]})
Can anyone guide me how I can do the search with or condition in python motor?
The or condition is used to check whether the data of particular student is entered in both the fields or not.
You write, "I end up with an error", but it is very difficult for anyone to answer your question if you don't tell us what the error is!
In this particular case I think I know the problem. In Python, all field names must be quoted. The proper syntax is:
doc = yield db.student.find_one({ "$or": [{"academy": name}, {"sports": name}]})

Python Eve - where clause using objectid

I have the following resource defined in settings.py,
builds = {
'item_title': 'builds',
'schema': {
'sources': {
'type': 'list',
'schema': {
'type': 'objectid',
'data_relation': {
'resource': 'sources',
'embeddable': True,
}
}
},
'checkin_id': {
'type': 'string',
'required': True,
'minlength': 1,
},
}
}
When I try to filter based on a member whose value is an objectid, I get empty list.
http://127.0.0.1:5000/builds?where={"sources":"54e328ec537d3d20bbdf2ed5"}
54e328ec537d3d20bbdf2ed5 is the id of source
Is there anyway to do this?
Your query should work just fine assuming that you actually have the 54e328ec537d3d20bbdf2ed5 value included in any sources field within any builds document.
What I mean is, you can't query the builds endpoint for the existence of a document in the sources endpoint (you can of course do that at the sources endpoint.) But, if you actually store a builds document and it references a sources document, then you query will work fine because what you are actually asking is "get me all builds documents which have a reference to this sources document". For example, if you POST a document like this to the builds endpoint:
{
"sources": ["54e328ec537d3d20bbdf2ed5"]
"checkin_id": "A"
}
Then this query:
http://127.0.0.1:5000/builds?where={"sources":"54e328ec537d3d20bbdf2ed5"}
Will return that one document. Of course since you defined sources as embeddable you can also do:
http://127.0.0.1:5000/builds?where={"sources":"54e328ec537d3d20bbdf2ed5"}&embedded={"sources":1}
Which will get you referenced documents embedded along with any matching document, like so:
{
"sources": [{"field1": "hey", "field2":"I'm an embedded source"}]
"checkin_id": "A"
}
Whereas you would get a 'raw' document without the explicit embed. It is probably worth mentioning that you can also enable predefined embedding of referenced resources, so your clients don't have to explicitly request an embed.
Hope this helps.
New to Eve but I have an advance on Nicola's "should work", because my experience is that it does not and as this question is what comes up when looking trying to deal with the frustration of figuring out why...
Debugging this the library got me to the point where Eve automagically decides that something with a signature that looks like "54e328ec537d3d20bbdf2ed5" should be cast to an ObjectId, which is all good. However, then the comparison of type ObjectId:54e328ec537d3d20bbdf2ed5 against type string:54e328ec537d3d20bbdf2ed5 is not an equality so your filter returns no results
The really simple solution is to change checkin_id to ObjectId. Eve starters can be assured you don't need all the additional decorations, so in the above example just change 'type':'string' to 'type':'objectId' and will be good. Specifically, if you have calling code where this field is defined as a string, you can leave it as it is, the cast will occur within eve as described above and it will just work as expected.
edit - See also eve's schema level "query_objectid_as_string" configuration setting for which upon reading seems to override this behaviour.

Categories