Merge branch 'master' of github.com:oasis-open/cti-python-stix2

master
chrisr3d 2019-09-03 13:47:43 +02:00
commit a739c1154e
12 changed files with 292 additions and 91 deletions

View File

@ -1,6 +1,15 @@
CHANGELOG CHANGELOG
========= =========
1.1.3 - 2019-08-12
* #258 Ignores empty values for optional fields
* #259 Adds support for lang granular markings
* #261 Prevents instantiation or serialization of TLP marking-definitions that don't follow the spec
* #262 Supports actual objects in _valid_refs instead of just strings
* #264 Supports accessing objects in bundles via STIX Object IDs
* #274 Fixes bug parsing bundle containing custom objects
1.1.2 - 2019-02-13 1.1.2 - 2019-02-13
* #86 Adds helper function to Location objects to generate a URL to the location in an online map engine. * #86 Adds helper function to Location objects to generate a URL to the location in an online map engine.

View File

@ -135,6 +135,9 @@ select additional or substitute Maintainers, per `consensus agreements
https://github.com/emmanvg/; WWW: `MITRE https://github.com/emmanvg/; WWW: `MITRE
Corporation <https://www.mitre.org/>`__ Corporation <https://www.mitre.org/>`__
- `Jason Keirstead <mailto:Jason.Keirstead@ca.ibm.com>`__; GitHub ID:
https://github.com/JasonKeirstead; WWW: `IBM <http://www.ibm.com/>`__
About OASIS TC Open Repositories About OASIS TC Open Repositories
-------------------------------- --------------------------------

View File

@ -175,9 +175,9 @@
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n", ".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n", ".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;identity&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;identity&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;id&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;identity--87aac643-341b-413a-b702-ea5820416155&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;id&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;identity--e7fd0fe0-25ff-4fcb-abe5-b6254a9d1a22&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;created&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2018-04-05T18:38:10.269Z&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;created&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2019-07-25T18:18:18.241Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;modified&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2018-04-05T18:38:10.269Z&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;modified&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2019-07-25T18:18:18.241Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;John Smith&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;John Smith&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;identity_class&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;individual&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;identity_class&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;individual&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;x_foo&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;bar&quot;</span>\n", " <span class=\"nt\">&quot;x_foo&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;bar&quot;</span>\n",
@ -194,8 +194,6 @@
} }
], ],
"source": [ "source": [
"from stix2 import Identity\n",
"\n",
"identity = Identity(name=\"John Smith\",\n", "identity = Identity(name=\"John Smith\",\n",
" identity_class=\"individual\",\n", " identity_class=\"individual\",\n",
" custom_properties={\n", " custom_properties={\n",
@ -289,9 +287,9 @@
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n", ".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n", ".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;identity&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;identity&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;id&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;identity--a1ad0a6f-39ab-4642-9a72-aaa198b1eee2&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;id&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;identity--033b5f42-c94f-488f-8efa-2b6a167f0d6f&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;created&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2018-04-05T18:38:12.270Z&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;created&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2019-07-25T18:18:21.352Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;modified&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2018-04-05T18:38:12.270Z&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;modified&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2019-07-25T18:18:21.352Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;John Smith&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;John Smith&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;identity_class&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;individual&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;identity_class&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;individual&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;x_foo&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;bar&quot;</span>\n", " <span class=\"nt\">&quot;x_foo&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;bar&quot;</span>\n",
@ -426,6 +424,113 @@
"print(identity3.x_foo)" "print(identity3.x_foo)"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To remove a custom properties, use `new_version()` and set it to `None`."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
".highlight { background: #f8f8f8; }\n",
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
".highlight .o { color: #666666 } /* Operator */\n",
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
".highlight .go { color: #888888 } /* Generic.Output */\n",
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
".highlight .m { color: #666666 } /* Literal.Number */\n",
".highlight .s { color: #BA2121 } /* Literal.String */\n",
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
".highlight .no { color: #880000 } /* Name.Constant */\n",
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
".highlight .nf { color: #0000FF } /* Name.Function */\n",
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
".highlight .nv { color: #19177C } /* Name.Variable */\n",
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;identity&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;id&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;identity--311b2d2d-f010-4473-83ec-1edf84858f4c&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;created&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2015-12-21T19:59:11.000Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;modified&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2019-07-25T18:18:25.927Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;John Smith&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;identity_class&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;individual&quot;</span>\n",
"<span class=\"p\">}</span>\n",
"</pre></div>\n"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"identity4 = identity3.new_version(x_foo=None)\n",
"print(identity4)"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},

View File

@ -2,7 +2,7 @@
"cells": [ "cells": [
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": 1,
"metadata": { "metadata": {
"nbsphinx": "hidden" "nbsphinx": "hidden"
}, },
@ -22,7 +22,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 2,
"metadata": { "metadata": {
"nbsphinx": "hidden" "nbsphinx": "hidden"
}, },
@ -63,12 +63,12 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"To create a new version of an existing object, specify the property(ies) you want to change and their new values:" "To create a new version of an existing object, specify the property(ies) you want to change and their new values. For example, here we change the label from \"anomalous-activity\" to \"malicious-activity\":"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 3,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -144,12 +144,13 @@
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n", ".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n", ".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;indicator&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;indicator&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;id&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;indicator--dd052ff6-e404-444b-beb9-eae96d1e79ea&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;id&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;indicator--8ad18fc7-457c-475d-b292-1ec44febe0fd&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;created&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2016-01-01T08:00:00.000Z&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;created&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2016-01-01T08:00:00.000Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;modified&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2018-04-05T20:02:51.161Z&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;modified&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2019-07-25T17:59:34.815Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;File hash for Foobar malware&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;File hash for Foobar malware&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;description&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;A file indicator&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;pattern&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;[file:hashes.md5 = &#39;d41d8cd98f00b204e9800998ecf8427e&#39;]&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;pattern&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;[file:hashes.md5 = &#39;d41d8cd98f00b204e9800998ecf8427e&#39;]&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;valid_from&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2018-04-05T20:02:51.138312Z&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;valid_from&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2019-07-25T17:59:34.779826Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;labels&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n", " <span class=\"nt\">&quot;labels&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
" <span class=\"s2\">&quot;malicious-activity&quot;</span>\n", " <span class=\"s2\">&quot;malicious-activity&quot;</span>\n",
" <span class=\"p\">]</span>\n", " <span class=\"p\">]</span>\n",
@ -160,7 +161,7 @@
"<IPython.core.display.HTML object>" "<IPython.core.display.HTML object>"
] ]
}, },
"execution_count": 4, "execution_count": 3,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
@ -170,6 +171,7 @@
"\n", "\n",
"indicator = Indicator(created=\"2016-01-01T08:00:00.000Z\",\n", "indicator = Indicator(created=\"2016-01-01T08:00:00.000Z\",\n",
" name=\"File hash for suspicious file\",\n", " name=\"File hash for suspicious file\",\n",
" description=\"A file indicator\",\n",
" labels=[\"anomalous-activity\"],\n", " labels=[\"anomalous-activity\"],\n",
" pattern=\"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']\")\n", " pattern=\"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']\")\n",
"\n", "\n",
@ -187,7 +189,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 4,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -205,6 +207,117 @@
"indicator.new_version(id=\"indicator--cc42e358-8b9b-493c-9646-6ecd73b41c21\")" "indicator.new_version(id=\"indicator--cc42e358-8b9b-493c-9646-6ecd73b41c21\")"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can remove optional or custom properties by setting them to `None` when you call `new_version()`."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
".highlight { background: #f8f8f8; }\n",
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
".highlight .o { color: #666666 } /* Operator */\n",
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
".highlight .go { color: #888888 } /* Generic.Output */\n",
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
".highlight .m { color: #666666 } /* Literal.Number */\n",
".highlight .s { color: #BA2121 } /* Literal.String */\n",
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
".highlight .no { color: #880000 } /* Name.Constant */\n",
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
".highlight .nf { color: #0000FF } /* Name.Function */\n",
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
".highlight .nv { color: #19177C } /* Name.Variable */\n",
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;indicator&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;id&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;indicator--8ad18fc7-457c-475d-b292-1ec44febe0fd&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;created&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2016-01-01T08:00:00.000Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;modified&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2019-07-25T17:59:42.648Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;File hash for suspicious file&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;pattern&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;[file:hashes.md5 = &#39;d41d8cd98f00b204e9800998ecf8427e&#39;]&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;valid_from&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2019-07-25T17:59:34.779826Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;labels&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
" <span class=\"s2\">&quot;anomalous-activity&quot;</span>\n",
" <span class=\"p\">]</span>\n",
"<span class=\"p\">}</span>\n",
"</pre></div>\n"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"indicator3 = indicator.new_version(description=None)\n",
"print(indicator3)"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {
@ -292,15 +405,15 @@
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n", ".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n", ".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
" <span class=\"nt\">&quot;type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;indicator&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;type&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;indicator&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;id&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;indicator--dd052ff6-e404-444b-beb9-eae96d1e79ea&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;id&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;indicator--8ad18fc7-457c-475d-b292-1ec44febe0fd&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;created&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2016-01-01T08:00:00.000Z&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;created&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2016-01-01T08:00:00.000Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;modified&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2018-04-05T20:02:54.704Z&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;modified&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2019-07-25T17:59:52.198Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;File hash for Foobar malware&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;File hash for suspicious file&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;pattern&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;[file:hashes.md5 = &#39;d41d8cd98f00b204e9800998ecf8427e&#39;]&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;pattern&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;[file:hashes.md5 = &#39;d41d8cd98f00b204e9800998ecf8427e&#39;]&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;valid_from&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2018-04-05T20:02:51.138312Z&quot;</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;valid_from&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;2019-07-25T17:59:34.779826Z&quot;</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;revoked&quot;</span><span class=\"p\">:</span> <span class=\"kc\">true</span><span class=\"p\">,</span>\n", " <span class=\"nt\">&quot;revoked&quot;</span><span class=\"p\">:</span> <span class=\"kc\">true</span><span class=\"p\">,</span>\n",
" <span class=\"nt\">&quot;labels&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n", " <span class=\"nt\">&quot;labels&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
" <span class=\"s2\">&quot;malicious-activity&quot;</span>\n", " <span class=\"s2\">&quot;anomalous-activity&quot;</span>\n",
" <span class=\"p\">]</span>\n", " <span class=\"p\">]</span>\n",
"<span class=\"p\">}</span>\n", "<span class=\"p\">}</span>\n",
"</pre></div>\n" "</pre></div>\n"
@ -315,8 +428,8 @@
} }
], ],
"source": [ "source": [
"indicator2 = indicator2.revoke()\n", "indicator4 = indicator3.revoke()\n",
"print(indicator2)" "print(indicator4)"
] ]
} }
], ],

View File

@ -1,5 +1,5 @@
[bumpversion] [bumpversion]
current_version = 1.1.2 current_version = 1.1.3
commit = True commit = True
tag = True tag = True

View File

@ -27,6 +27,7 @@ setup(
version=get_version(), version=get_version(),
description='Produce and consume STIX 2 JSON content', description='Produce and consume STIX 2 JSON content',
long_description=get_long_description(), long_description=get_long_description(),
long_description_content_type='text/x-rst',
url='https://oasis-open.github.io/cti-documentation/', url='https://oasis-open.github.io/cti-documentation/',
author='OASIS Cyber Threat Intelligence Technical Committee', author='OASIS Cyber Threat Intelligence Technical Committee',
author_email='cti-users@lists.oasis-open.org', author_email='cti-users@lists.oasis-open.org',
@ -47,7 +48,7 @@ setup(
'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.7',
], ],
keywords='stix stix2 json cti cyber threat intelligence', keywords='stix stix2 json cti cyber threat intelligence',
packages=find_packages(exclude=['*.test']), packages=find_packages(exclude=['*.test', '*.test.*']),
install_requires=[ install_requires=[
'python-dateutil', 'python-dateutil',
'pytz', 'pytz',

View File

@ -125,15 +125,13 @@ def rel_fs_store():
def test_filesystem_source_nonexistent_folder(): def test_filesystem_source_nonexistent_folder():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.FileSystemSource('nonexistent-folder') stix2.FileSystemSource('nonexistent-folder')
assert "for STIX data does not exist" in str(excinfo)
def test_filesystem_sink_nonexistent_folder(): def test_filesystem_sink_nonexistent_folder():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.FileSystemSink('nonexistent-folder') stix2.FileSystemSink('nonexistent-folder')
assert "for STIX data does not exist" in str(excinfo)
def test_filesystem_source_bad_json_file(fs_source, bad_json_files): def test_filesystem_source_bad_json_file(fs_source, bad_json_files):
@ -441,9 +439,8 @@ def test_filesystem_attempt_stix_file_overwrite(fs_store):
) )
# Now attempt to overwrite the existing file # Now attempt to overwrite the existing file
with pytest.raises(DataSourceError) as excinfo: with pytest.raises(DataSourceError):
fs_store.add(camp8) fs_store.add(camp8)
assert "Attempted to overwrite file" in str(excinfo)
os.remove(filepath) os.remove(filepath)

View File

@ -257,7 +257,7 @@ def test_and_observable_expression():
def test_invalid_and_observable_expression(): def test_invalid_and_observable_expression():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.AndBooleanExpression([ stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression( stix2.EqualityComparisonExpression(
"user-account:display_name", "user-account:display_name",
@ -268,7 +268,6 @@ def test_invalid_and_observable_expression():
stix2.StringConstant("admin"), stix2.StringConstant("admin"),
), ),
]) ])
assert "All operands to an 'AND' expression must have the same object type" in str(excinfo)
def test_hex(): def test_hex():
@ -352,30 +351,26 @@ def test_list2():
def test_invalid_constant_type(): def test_invalid_constant_type():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.EqualityComparisonExpression( stix2.EqualityComparisonExpression(
"artifact:payload_bin", "artifact:payload_bin",
{'foo': 'bar'}, {'foo': 'bar'},
) )
assert 'Unable to create a constant' in str(excinfo)
def test_invalid_integer_constant(): def test_invalid_integer_constant():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.IntegerConstant('foo') stix2.IntegerConstant('foo')
assert 'must be an integer' in str(excinfo)
def test_invalid_timestamp_constant(): def test_invalid_timestamp_constant():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.TimestampConstant('foo') stix2.TimestampConstant('foo')
assert 'Must be a datetime object or timestamp string' in str(excinfo)
def test_invalid_float_constant(): def test_invalid_float_constant():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.FloatConstant('foo') stix2.FloatConstant('foo')
assert 'must be a float' in str(excinfo)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -400,9 +395,8 @@ def test_boolean_constant(data, result):
def test_invalid_boolean_constant(): def test_invalid_boolean_constant():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.BooleanConstant('foo') stix2.BooleanConstant('foo')
assert 'must be a boolean' in str(excinfo)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -412,21 +406,18 @@ def test_invalid_boolean_constant():
], ],
) )
def test_invalid_hash_constant(hashtype, data): def test_invalid_hash_constant(hashtype, data):
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.HashConstant(data, hashtype) stix2.HashConstant(data, hashtype)
assert 'is not a valid {} hash'.format(hashtype) in str(excinfo)
def test_invalid_hex_constant(): def test_invalid_hex_constant():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.HexConstant('mm') stix2.HexConstant('mm')
assert "must contain an even number of hexadecimal characters" in str(excinfo)
def test_invalid_binary_constant(): def test_invalid_binary_constant():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.BinaryConstant('foo') stix2.BinaryConstant('foo')
assert 'must contain a base64' in str(excinfo)
def test_escape_quotes_and_backslashes(): def test_escape_quotes_and_backslashes():
@ -459,15 +450,13 @@ def test_repeat_qualifier():
def test_invalid_repeat_qualifier(): def test_invalid_repeat_qualifier():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.RepeatQualifier('foo') stix2.RepeatQualifier('foo')
assert 'is not a valid argument for a Repeat Qualifier' in str(excinfo)
def test_invalid_within_qualifier(): def test_invalid_within_qualifier():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.WithinQualifier('foo') stix2.WithinQualifier('foo')
assert 'is not a valid argument for a Within Qualifier' in str(excinfo)
def test_startstop_qualifier(): def test_startstop_qualifier():
@ -485,19 +474,17 @@ def test_startstop_qualifier():
def test_invalid_startstop_qualifier(): def test_invalid_startstop_qualifier():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.StartStopQualifier( stix2.StartStopQualifier(
'foo', 'foo',
stix2.TimestampConstant('2016-06-01T00:00:00Z'), stix2.TimestampConstant('2016-06-01T00:00:00Z'),
) )
assert 'is not a valid argument for a Start/Stop Qualifier' in str(excinfo)
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.StartStopQualifier( stix2.StartStopQualifier(
datetime.date(2016, 6, 1), datetime.date(2016, 6, 1),
'foo', 'foo',
) )
assert 'is not a valid argument for a Start/Stop Qualifier' in str(excinfo)
def test_make_constant_already_a_constant(): def test_make_constant_already_a_constant():

View File

@ -124,15 +124,13 @@ def rel_fs_store():
def test_filesystem_source_nonexistent_folder(): def test_filesystem_source_nonexistent_folder():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.FileSystemSource('nonexistent-folder') stix2.FileSystemSource('nonexistent-folder')
assert "for STIX data does not exist" in str(excinfo)
def test_filesystem_sink_nonexistent_folder(): def test_filesystem_sink_nonexistent_folder():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.FileSystemSink('nonexistent-folder') stix2.FileSystemSink('nonexistent-folder')
assert "for STIX data does not exist" in str(excinfo)
def test_filesystem_source_bad_json_file(fs_source, bad_json_files): def test_filesystem_source_bad_json_file(fs_source, bad_json_files):

View File

@ -257,7 +257,7 @@ def test_and_observable_expression():
def test_invalid_and_observable_expression(): def test_invalid_and_observable_expression():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.AndBooleanExpression([ stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression( stix2.EqualityComparisonExpression(
"user-account:display_name", "user-account:display_name",
@ -268,7 +268,6 @@ def test_invalid_and_observable_expression():
stix2.StringConstant("admin"), stix2.StringConstant("admin"),
), ),
]) ])
assert "All operands to an 'AND' expression must have the same object type" in str(excinfo)
def test_hex(): def test_hex():
@ -352,30 +351,26 @@ def test_list2():
def test_invalid_constant_type(): def test_invalid_constant_type():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.EqualityComparisonExpression( stix2.EqualityComparisonExpression(
"artifact:payload_bin", "artifact:payload_bin",
{'foo': 'bar'}, {'foo': 'bar'},
) )
assert 'Unable to create a constant' in str(excinfo)
def test_invalid_integer_constant(): def test_invalid_integer_constant():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.IntegerConstant('foo') stix2.IntegerConstant('foo')
assert 'must be an integer' in str(excinfo)
def test_invalid_timestamp_constant(): def test_invalid_timestamp_constant():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.TimestampConstant('foo') stix2.TimestampConstant('foo')
assert 'Must be a datetime object or timestamp string' in str(excinfo)
def test_invalid_float_constant(): def test_invalid_float_constant():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.FloatConstant('foo') stix2.FloatConstant('foo')
assert 'must be a float' in str(excinfo)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -400,9 +395,8 @@ def test_boolean_constant(data, result):
def test_invalid_boolean_constant(): def test_invalid_boolean_constant():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.BooleanConstant('foo') stix2.BooleanConstant('foo')
assert 'must be a boolean' in str(excinfo)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -412,21 +406,18 @@ def test_invalid_boolean_constant():
], ],
) )
def test_invalid_hash_constant(hashtype, data): def test_invalid_hash_constant(hashtype, data):
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.HashConstant(data, hashtype) stix2.HashConstant(data, hashtype)
assert 'is not a valid {} hash'.format(hashtype) in str(excinfo)
def test_invalid_hex_constant(): def test_invalid_hex_constant():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.HexConstant('mm') stix2.HexConstant('mm')
assert "must contain an even number of hexadecimal characters" in str(excinfo)
def test_invalid_binary_constant(): def test_invalid_binary_constant():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.BinaryConstant('foo') stix2.BinaryConstant('foo')
assert 'must contain a base64' in str(excinfo)
def test_escape_quotes_and_backslashes(): def test_escape_quotes_and_backslashes():
@ -459,15 +450,13 @@ def test_repeat_qualifier():
def test_invalid_repeat_qualifier(): def test_invalid_repeat_qualifier():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.RepeatQualifier('foo') stix2.RepeatQualifier('foo')
assert 'is not a valid argument for a Repeat Qualifier' in str(excinfo)
def test_invalid_within_qualifier(): def test_invalid_within_qualifier():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.WithinQualifier('foo') stix2.WithinQualifier('foo')
assert 'is not a valid argument for a Within Qualifier' in str(excinfo)
def test_startstop_qualifier(): def test_startstop_qualifier():
@ -485,19 +474,17 @@ def test_startstop_qualifier():
def test_invalid_startstop_qualifier(): def test_invalid_startstop_qualifier():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.StartStopQualifier( stix2.StartStopQualifier(
'foo', 'foo',
stix2.TimestampConstant('2016-06-01T00:00:00Z'), stix2.TimestampConstant('2016-06-01T00:00:00Z'),
) )
assert 'is not a valid argument for a Start/Stop Qualifier' in str(excinfo)
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
stix2.StartStopQualifier( stix2.StartStopQualifier(
datetime.date(2016, 6, 1), datetime.date(2016, 6, 1),
'foo', 'foo',
) )
assert 'is not a valid argument for a Start/Stop Qualifier' in str(excinfo)
def test_make_constant_already_a_constant(): def test_make_constant_already_a_constant():

View File

@ -1 +1 @@
__version__ = "1.1.2" __version__ = "1.1.3"

View File

@ -34,9 +34,10 @@ commands =
[testenv:packaging] [testenv:packaging]
deps = deps =
readme_renderer twine
commands = commands =
python setup.py check -r -s python setup.py bdist_wheel --universal
twine check dist/*
[travis] [travis]
python = python =