├── .gitignore ├── .travis.yml ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.rst ├── pycot ├── __init__.py ├── classes.py ├── constants.py ├── exceptions.py ├── functions.py └── utils.py ├── requirements.txt ├── setup.cfg ├── setup.py ├── tests ├── __init__.py ├── constants.py ├── context.py └── test_cot.py └── tox.ini /.gitignore: -------------------------------------------------------------------------------- 1 | *.deb 2 | *.egg 3 | *.egg-info/ 4 | *.egg/ 5 | *.ignore 6 | *.py[co] 7 | *.py[oc] 8 | *.spl 9 | *.vagrant 10 | .DS_Store 11 | .coverage 12 | .eggs/ 13 | .eggs/* 14 | .idea 15 | .idea/ 16 | .pt 17 | .vagrant/ 18 | RELEASE-VERSION.txt 19 | build/ 20 | cover/ 21 | dist/ 22 | dump.rdb 23 | flake8.log 24 | local/ 25 | local_* 26 | metadata/ 27 | nosetests.xml 28 | output.xml 29 | pylint.log 30 | redis-server.log 31 | redis-server/ 32 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | python: 4 | - "3.6" 5 | - "3.7" 6 | - "3.8" 7 | 8 | install: 9 | - python setup.py install 10 | - pip install tox 11 | 12 | script: 13 | - tox 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Orion Labs, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst LICENSE requirements.txt 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Python Cursor on Target Module. 2 | # 3 | # Source:: https://github.com/ampledata/pycot 4 | # Author:: Greg Albrecht W2GMD 5 | # Copyright:: Copyright 2020 Orion Labs, Inc. 6 | # License:: Apache License, Version 2.0 7 | # 8 | 9 | 10 | .DEFAULT_GOAL := all 11 | 12 | 13 | all: develop 14 | 15 | install_requirements: 16 | pip install -r requirements.txt 17 | 18 | develop: remember 19 | python setup.py develop 20 | 21 | install: remember 22 | python setup.py install 23 | 24 | uninstall: 25 | pip uninstall -y pycot 26 | 27 | reinstall: uninstall install 28 | 29 | remember: 30 | @echo 31 | @echo "Hello from the Makefile..." 32 | @echo "Don't forget to run: 'make install_requirements'" 33 | @echo 34 | 35 | clean: 36 | @rm -rf *.egg* build dist *.py[oc] */*.py[co] cover doctest_pypi.cfg \ 37 | nosetests.xml pylint.log output.xml flake8.log tests.log \ 38 | test-result.xml htmlcov fab.log .coverage 39 | 40 | publish: 41 | python setup.py register sdist upload 42 | 43 | nosetests: remember 44 | python setup.py nosetests 45 | 46 | pep8: remember 47 | flake8 --max-complexity 12 --exit-zero pycot/*.py tests/*.py 48 | 49 | flake8: pep8 50 | 51 | lint: remember 52 | pylint --msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" \ 53 | -r n pycot/*.py tests/*.py || exit 0 54 | 55 | pylint: lint 56 | 57 | test: lint pep8 nosetests 58 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | DEPRECATED 2 | ********** 3 | PyCOT has been deprecated. Please see my other projects based on PyTAK: https://github.com/ampledata/pytak 4 | 5 | 6 | pycot - Python Cursor on Target Module 7 | ************************************** 8 | 9 | Renders and Parses Cursor on Target XML events. 10 | 11 | 12 | Installation 13 | ============ 14 | Install from pypi using pip: ``pip install pycot`` 15 | 16 | 17 | Build Status 18 | ============ 19 | 20 | Master: 21 | 22 | .. image:: https://travis-ci.com/ampledata/pycot.svg?branch=master 23 | :target: https://travis-ci.com/ampledata/pycot 24 | 25 | Develop: 26 | 27 | .. image:: https://travis-ci.com/ampledata/pycot.svg?branch=develop 28 | :target: https://travis-ci.com/ampledata/pycot 29 | 30 | 31 | Source 32 | ====== 33 | Github: https://github.com/ampledata/pycot 34 | 35 | Author 36 | ====== 37 | Greg Albrecht W2GMD oss@undef.net 38 | 39 | https://www.orionlabs.io/ 40 | 41 | Copyright 42 | ========= 43 | Copyright 2020 Orion Labs, Inc. 44 | 45 | License 46 | ======= 47 | Apache License, Version 2.0. See LICENSE for details. 48 | -------------------------------------------------------------------------------- /pycot/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Python Cursor on Target Module. 5 | 6 | """ 7 | Python Cursor on Target Module. 8 | ~~~~ 9 | 10 | 11 | :author: Greg Albrecht W2GMD 12 | :copyright: Copyright 2020 Orion Labs, Inc. 13 | :license: Apache License, Version 2.0 14 | :source: 15 | 16 | """ 17 | 18 | from .constants import LOG_LEVEL, LOG_FORMAT # NOQA 19 | 20 | from .exceptions import UnsupportedEvent # NOQA 21 | 22 | from .classes import (Event, Point, Detail, UID, Contact, EventType, # NOQA 23 | AtomEventType, DataEventType, Track, Remarks, Chat, 24 | ChatGroup, Link) 25 | 26 | from .functions import parse_event_type # NOQA 27 | 28 | __author__ = "Greg Albrecht W2GMD " 29 | __copyright__ = "Copyright 2020 Orion Labs, Inc." 30 | __license__ = "Apache License, Version 2.0" 31 | -------------------------------------------------------------------------------- /pycot/classes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Python Cursor on Target Module Class Definitions.""" 5 | 6 | import datetime 7 | import uuid 8 | 9 | import gexml 10 | 11 | __author__ = "Greg Albrecht W2GMD " 12 | __copyright__ = "Copyright 2020 Orion Labs, Inc." 13 | __license__ = "Apache License, Version 2.0" 14 | 15 | 16 | class Point(gexml.Model): 17 | """CoT Point""" 18 | class meta: # NOQA pylint: disable=invalid-name,missing-class-docstring,too-few-public-methods 19 | tagname = 'point' 20 | lat = gexml.fields.Float() 21 | lon = gexml.fields.Float() 22 | hae = gexml.fields.Float(required=False) 23 | ce = gexml.fields.Float() 24 | le = gexml.fields.Float() 25 | version = gexml.fields.String(required=False) 26 | 27 | 28 | class UID(gexml.Model): 29 | """CoT UID""" 30 | class meta: # NOQA pylint: disable=invalid-name,missing-class-docstring,too-few-public-methods 31 | tagname = 'uid' 32 | Droid = gexml.fields.String() 33 | version = gexml.fields.String(required=False) 34 | 35 | 36 | class Contact(gexml.Model): 37 | """CoT Contact""" 38 | class meta: # NOQA pylint: disable=invalid-name,missing-class-docstring,too-few-public-methods 39 | tagname = 'contact' 40 | callsign = gexml.fields.String(required=False) 41 | freq = gexml.fields.String(required=False) 42 | email = gexml.fields.String(required=False) 43 | dsn = gexml.fields.String(required=False) 44 | phone = gexml.fields.String(required=False) 45 | modulation = gexml.fields.String(required=False) 46 | hostname = gexml.fields.String(required=False) 47 | version = gexml.fields.String(required=False) 48 | 49 | 50 | class ChatGroup(gexml.Model): 51 | class meta: 52 | tagname = 'chatgrp' 53 | uid0 = gexml.fields.String(required=False) 54 | uid1 = gexml.fields.String(required=False) 55 | id = gexml.fields.String(required=False) 56 | 57 | 58 | class Chat(gexml.Model): 59 | """CoT Chat""" 60 | class meta: 61 | tagname = '__chat' 62 | senderCallsign = gexml.fields.String(required=False) 63 | chatroom = gexml.fields.String(required=False) 64 | groupOwner = gexml.fields.String(required=False) 65 | id = gexml.fields.String(required=False) 66 | parent = gexml.fields.String(required=False) 67 | chatgrp = gexml.fields.Model(ChatGroup, required=False) 68 | 69 | 70 | class Track(gexml.Model): 71 | """CoT Track""" 72 | class meta: # NOQA pylint: disable=invalid-name,missing-class-docstring,too-few-public-methods 73 | tagname = 'track' 74 | course = gexml.fields.String() 75 | speed = gexml.fields.String() 76 | slope = gexml.fields.String(required=False) 77 | eCourse = gexml.fields.String(required=False) 78 | eSpeed = gexml.fields.String(required=False) 79 | eSlope = gexml.fields.String(required=False) 80 | version = gexml.fields.String(required=False) 81 | 82 | 83 | class Remarks(gexml.Model): 84 | """CoT Track""" 85 | class meta: # NOQA pylint: disable=invalid-name,missing-class-docstring,too-few-public-methods 86 | tagname = 'remarks' 87 | value = gexml.fields.String(tagname='.', required=False) 88 | source = gexml.fields.String(required=False) 89 | time = gexml.fields.String(required=False) 90 | to = gexml.fields.String(required=False) 91 | keywords = gexml.fields.String(required=False) 92 | version = gexml.fields.String(required=False) 93 | 94 | 95 | class Link(gexml.Model): 96 | class meta: 97 | tagname = "link" 98 | uid = gexml.fields.String(required=False) 99 | production_time = gexml.fields.String(required=False) 100 | event_type = gexml.fields.String(attrname="type") 101 | url = gexml.fields.String(required=False) 102 | parent_callsign = gexml.fields.String(required=False) 103 | remarks = gexml.fields.String(required=False) 104 | mime = gexml.fields.String(required=False) 105 | version = gexml.fields.String(required=False) 106 | relation = gexml.fields.String(required=False) 107 | 108 | 109 | class Detail(gexml.Model): 110 | """CoT Detail""" 111 | class meta: # NOQA pylint: disable=invalid-name,missing-class-docstring,too-few-public-methods 112 | tagname = 'detail' 113 | uid = gexml.fields.Model(UID, required=False) 114 | contact = gexml.fields.Model(Contact, required=False) 115 | track = gexml.fields.Model(Track, required=False) 116 | remarks = gexml.fields.Model(Remarks, required=False) 117 | link = gexml.fields.Model(Link, required=False) 118 | chat = gexml.fields.Model(Chat, required=False) 119 | 120 | 121 | class Event(gexml.Model): 122 | """CoT Event Object""" 123 | class meta: # NOQA pylint: disable=invalid-name,missing-class-docstring,too-few-public-methods 124 | tagname = 'event' 125 | 126 | __str__ = gexml.Model.render 127 | 128 | version = gexml.fields.String(required=True) # default="2.0" 129 | event_type = gexml.fields.String(attrname="type") 130 | 131 | uid = gexml.fields.String(required=True) # default=uuid.uuid4() 132 | 133 | time = gexml.fields.DateTime(required=True) # NOQA default=datetime.datetime.now(datetime.timezone.utc) 134 | start = gexml.fields.DateTime(required=False) 135 | stale = gexml.fields.DateTime(required=False) 136 | point = gexml.fields.Model(Point, required=False) 137 | detail = gexml.fields.Model(Detail, required=False) 138 | access = gexml.fields.String(required=False) 139 | qos = gexml.fields.String(required=False) 140 | opex = gexml.fields.String(required=False) 141 | how = gexml.fields.String() 142 | 143 | 144 | class EventType: # pylint: disable=too-few-public-methods 145 | """CoT EventType""" 146 | 147 | describes = None 148 | type_fields = [] 149 | 150 | def __init__(self, event_type=None): 151 | self.event_type = event_type 152 | split_event = event_type.split('-') 153 | data = dict(zip(self.type_fields[0:len(split_event)], split_event)) 154 | for key, val in data.items(): 155 | setattr(self, key, val) 156 | 157 | def __str__(self): 158 | return self.event_type 159 | 160 | 161 | class AtomEventType(EventType): # pylint: disable=too-few-public-methods 162 | """CoT AtomEventType 163 | a - atoms (anything you drop on your foot), based on MS2525B. 164 | """ 165 | describes = 'Thing' 166 | type_fields = ['_describes', 'affiliation', 'battle_dimension', 'function'] 167 | 168 | 169 | class DataEventType(EventType): # pylint: disable=too-few-public-methods 170 | """CoT DataEventType""" 171 | describes = 'Data' 172 | type_fields = ['_describes', 'dimension'] 173 | 174 | test_chat = """ 175 | 176 | <__chat parent="RootContactGroup" groupOwner="false" chatroom="All Chat Rooms" id="All Chat Rooms" senderCallsign="FFF-1">FFF-1<__serverdestination destinations="172.17.2.246:8087:tcp:FFF-1"/> 177 | """ 178 | -------------------------------------------------------------------------------- /pycot/constants.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Python Cursor on Target Module Constants.""" 5 | 6 | import logging 7 | import os 8 | 9 | __author__ = 'Greg Albrecht W2GMD ' 10 | __copyright__ = 'Copyright 2020 Orion Labs, Inc.' 11 | __license__ = 'Apache License, Version 2.0' 12 | 13 | 14 | if bool(os.environ.get('DEBUG')): 15 | LOG_LEVEL = logging.DEBUG 16 | LOG_FORMAT = logging.Formatter( 17 | ('%(asctime)s pycot %(levelname)s %(name)s.%(funcName)s:%(lineno)d - ' 18 | '%(message)s')) 19 | logging.debug('pycot Debugging Enabled via DEBUG Environment Variable.') 20 | else: 21 | LOG_LEVEL = logging.INFO 22 | LOG_FORMAT = logging.Formatter( 23 | ('%(asctime)s pycot %(levelname)s - %(message)s')) 24 | 25 | 26 | DEFAULT_COT_PORT: int = 8087 27 | -------------------------------------------------------------------------------- /pycot/exceptions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Python Cursor on Target Module Exceptions.""" 5 | 6 | __author__ = 'Greg Albrecht ' 7 | __copyright__ = 'Copyright 2020 Orion Labs, Inc.' 8 | __license__ = 'Apache License, Version 2.0' 9 | 10 | 11 | class UnsupportedEvent(Exception): 12 | """Unsupported CoT Event.""" 13 | pass 14 | -------------------------------------------------------------------------------- /pycot/functions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Python Cursor on Target Module Function Definitions.""" 5 | 6 | import pycot 7 | 8 | __author__ = 'Greg Albrecht ' 9 | __copyright__ = 'Copyright 2020 Orion Labs, Inc.' 10 | __license__ = 'Apache License, Version 2.0' 11 | 12 | 13 | def parse_event_type(event_type: str) -> pycot.EventType: 14 | """Parses CoT Event Types from CoT Events.""" 15 | if event_type.startswith('a'): 16 | return pycot.AtomEventType(event_type) 17 | elif event_type.startswith('b'): 18 | return pycot.DataEventType(event_type) 19 | elif event_type.startswith('c'): 20 | describes = 'Capability' 21 | raise pycot.UnsupportedEvent(f'Unsupported Event type: {describes}') 22 | elif event_type.startswith('r'): 23 | describes = 'Reservation' 24 | raise pycot.UnsupportedEvent(f'Unsupported Event type: {describes}') 25 | elif event_type.startswith('t'): 26 | describes = 'Tasking' 27 | raise pycot.UnsupportedEvent(f'Unsupported Event type: {describes}') 28 | else: 29 | raise pycot.UnsupportedEvent(f'Unknown Event Type: {event_type}') 30 | -------------------------------------------------------------------------------- /pycot/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Python Cursor on Target Module Utility Function Definitions.""" 5 | 6 | import re 7 | 8 | __author__ = 'Greg Albrecht W2GMD ' 9 | __copyright__ = 'Copyright 2020 Orion Labs, Inc.' 10 | __license__ = 'Apache License, Version 2.0' 11 | 12 | 13 | def cast(typ, value): 14 | if typ is None or value is None: 15 | return value 16 | return typ(value) 17 | 18 | 19 | def parse_qos(qos): 20 | matches = re.search( 21 | r'(?\d)-(?\w)-(?\w)', qos) 22 | return matches 23 | 24 | 25 | def show_indent(outfile, level, pretty_print=True): 26 | if pretty_print: 27 | for _ in range(level): 28 | outfile.write(' ') 29 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # Python Distribution Package Requirements for Cursor on Target Module. 2 | # 3 | # Source:: https://github.com/ampledata/pycot 4 | # Author:: Greg Albrecht W2GMD 5 | # Copyright:: Copyright 2020 Orion Labs, Inc. 6 | # License:: Apache License, Version 2.0 7 | 8 | git+https://git@github.com/ampledata/gexml.git@master#egg=gexml 9 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | # Setup configuration for Python Cursor on Target Module. 2 | # 3 | # Source:: https://github.com/ampledata/pycot 4 | # Author:: Greg Albrecht W2GMD 5 | # Copyright:: Copyright 2020 Orion Labs, Inc. 6 | # License:: Apache License, Version 2.0 7 | # 8 | 9 | 10 | [aliases] 11 | test=pytest 12 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Setup for the Python Cursor on Target Module. 6 | 7 | :author: Greg Albrecht W2GMD 8 | :copyright: Copyright 2020 Orion Labs, Inc. 9 | :license: Apache License, Version 2.0 10 | :source: 11 | """ 12 | 13 | import os 14 | import setuptools 15 | import sys 16 | 17 | __title__ = 'pycot' 18 | __version__ = '2.5.1' 19 | __author__ = 'Greg Albrecht W2GMD ' 20 | __copyright__ = 'Copyright 2020 Orion Labs, Inc.' 21 | __license__ = 'Apache License, Version 2.0' 22 | 23 | 24 | def publish(): 25 | """Function for publishing package to pypi.""" 26 | if sys.argv[-1] == 'publish': 27 | os.system('python setup.py sdist') 28 | os.system('twine upload dist/*') 29 | sys.exit() 30 | 31 | 32 | publish() 33 | 34 | 35 | setuptools.setup( 36 | version=__version__, 37 | name=__title__, 38 | packages=[__title__], 39 | package_dir={__title__: __title__}, 40 | url=f'https://github.com/ampledata/{__title__}', 41 | description='Python Cursor on Target Module.', 42 | author='Greg Albrecht', 43 | author_email='oss@undef.net', 44 | package_data={'': ['LICENSE']}, 45 | license=open('LICENSE').read(), 46 | long_description=open('README.rst').read(), 47 | zip_safe=False, 48 | include_package_data=True, 49 | install_requires=[ 50 | 'gexml >= 1.0.0' 51 | ], 52 | classifiers=[ 53 | 'Programming Language :: Python', 54 | 'License :: OSI Approved :: Apache Software License' 55 | ], 56 | keywords=[ 57 | 'Cursor on Target', 'ATAK' 58 | ] 59 | ) 60 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Python Cursor on Target Module Tests.""" 5 | 6 | __author__ = 'Greg Albrecht W2GMD ' 7 | __copyright__ = 'Copyright 2020 Orion Labs, Inc.' 8 | __license__ = 'Apache License, Version 2.0' 9 | -------------------------------------------------------------------------------- /tests/constants.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Python Cursor on Target Module Test Constants.""" 5 | 6 | __author__ = 'Greg Albrecht W2GMD ' 7 | __copyright__ = 'Copyright 2020 Orion Labs, Inc.' 8 | __license__ = 'Apache License, Version 2.0' 9 | 10 | 11 | PANGRAM = 'the quick brown fox jumps over the lazy dog' 12 | ALPHABET = PANGRAM.replace(' ', '') 13 | 14 | NUMBERS = ''.join([str(x) for x in range(0, 10)]) 15 | POSITIVE_NUMBERS = NUMBERS[1:] 16 | ALPHANUM = ''.join([ALPHABET, NUMBERS]) 17 | -------------------------------------------------------------------------------- /tests/context.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Python Cursor on Target Module Test Context.""" 5 | 6 | import os 7 | import sys 8 | 9 | sys.path.insert(0, os.path.abspath('..')) 10 | 11 | import pycot # NOQA pylint: disable=C0413,W0611 12 | 13 | __author__ = 'Greg Albrecht W2GMD ' 14 | __copyright__ = 'Copyright 2020 Orion Labs, Inc.' 15 | __license__ = 'Apache License, Version 2.0' 16 | -------------------------------------------------------------------------------- /tests/test_cot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Python Cursor on Target Module Tests.""" 5 | 6 | import datetime 7 | import logging 8 | import unittest 9 | import uuid 10 | 11 | from .context import pycot 12 | 13 | # from . import constants 14 | 15 | __author__ = 'Greg Albrecht W2GMD ' 16 | __copyright__ = 'Copyright 2020 Orion Labs, Inc.' 17 | __license__ = 'Apache License, Version 2.0' 18 | 19 | 20 | class PYCOTTest(unittest.TestCase): # pylint: disable=R0904 21 | 22 | """Tests for the Python CoT Module.""" 23 | 24 | _logger = logging.getLogger(__name__) 25 | if not _logger.handlers: 26 | _logger.setLevel(pycot.LOG_LEVEL) 27 | _console_handler = logging.StreamHandler() 28 | _console_handler.setLevel(pycot.LOG_LEVEL) 29 | _console_handler.setFormatter(pycot.LOG_FORMAT) 30 | _logger.addHandler(_console_handler) 31 | _logger.propagate = False 32 | 33 | def test_generate_cot(self): 34 | """Tests generating a CoT XML Event using pycot.""" 35 | 36 | _keys = [ 37 | 'version', 'event_type', 'access', 'qos', 'opex', 'uid', 'time', 38 | 'start', 'stale', 'how', 'point', 'detail'] 39 | 40 | my_point = pycot.Point() 41 | my_point.lat = '37.76' 42 | my_point.lon = '-122.4975' 43 | my_point.ce = '45.3' 44 | my_point.le = '99.5' 45 | my_point.hae = '-42.6' 46 | 47 | evt = pycot.Event() 48 | evt.version = '0.1' 49 | evt.event_type = 'a-h-G-p-i' 50 | evt.uid = uuid.uuid4() 51 | evt.time = datetime.datetime.now() 52 | evt.how = 'h-e' 53 | evt.point = my_point 54 | 55 | self._logger.debug(evt.render(standalone=True, pretty=True)) 56 | 57 | # for k in _keys: 58 | # print getattr(e, k) 59 | 60 | # print dir(e.event_type) 61 | # print e.event_type.describes 62 | 63 | # with open('test.xml', 'w') as ofd: 64 | # print e.export(ofd, 1) 65 | 66 | def test_parse_cot(self): 67 | """Tests parsing a CoT XML Event using pycot.""" 68 | example_event = """ 69 | 76 | 77 | 78 | 80 | 81 | """ 82 | parsed = pycot.Event.parse(example_event) 83 | self._logger.debug(parsed) 84 | self._logger.debug(parsed.render(standalone=True)) 85 | self._logger.debug(dir(parsed)) 86 | self.assertEqual( 87 | parsed.render(standalone=True), 88 | ('') 95 | ) 96 | self.assertEqual(parsed.version, 2.0) 97 | self.assertEqual(parsed.uid, 'J-01334') 98 | 99 | # FIXME: These three tests fail b/c of 0000 instead of Z in TZ 100 | # self.assertEqual(str(parsed.time), '2005-04-05T11:43:38.07Z') 101 | # self.assertEqual(parsed.start, '2005-04-05T11:43:38.07Z') 102 | # self.assertEqual(parsed.stale, '2005-04-05T11:45:38.07Z') 103 | 104 | self.assertEqual(parsed.how, 'm-g') 105 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | 3 | [testenv] 4 | deps = pytest 5 | commands = pytest 6 | --------------------------------------------------------------------------------