From ac6827420096ccf13fe197ba639e78cf3adca654 Mon Sep 17 00:00:00 2001 From: Adam Baratz Date: Sun, 3 Nov 2019 23:06:52 -0500 Subject: [PATCH] Expand Topic class and add test coverage (#1252) * Expand Topic class and add test coverage * Add test coverage for Topic properties * Fix misspelling in comment --- github/GithubObject.py | 4 ++ github/Topic.py | 78 +++++++++++++++++++++++++--- tests/AllTests.py | 2 + tests/ReplayData/Topic.setUp.txt | 11 ++++ tests/Topic.py | 89 ++++++++++++++++++++++++++++++++ 5 files changed, 178 insertions(+), 6 deletions(-) create mode 100644 tests/ReplayData/Topic.setUp.txt create mode 100644 tests/Topic.py diff --git a/github/GithubObject.py b/github/GithubObject.py index 41581a56..d219b967 100644 --- a/github/GithubObject.py +++ b/github/GithubObject.py @@ -152,6 +152,10 @@ class GithubObject(object): def _makeIntAttribute(value): return GithubObject.__makeSimpleAttribute(value, six.integer_types) + @staticmethod + def _makeFloatAttribute(value): + return GithubObject.__makeSimpleAttribute(value, float) + @staticmethod def _makeBoolAttribute(value): return GithubObject.__makeSimpleAttribute(value, bool) diff --git a/github/Topic.py b/github/Topic.py index 99fed6e9..643b886b 100644 --- a/github/Topic.py +++ b/github/Topic.py @@ -26,9 +26,9 @@ from __future__ import absolute_import import github.GithubObject -class Topic(github.GithubObject.CompletableGithubObject): +class Topic(github.GithubObject.NonCompletableGithubObject): """ - This class represents topics as used by https://github.com/topics. The object refereence can be found here https://developer.github.com/v3/search/#search-topics + This class represents topics as used by https://github.com/topics. The object reference can be found here https://developer.github.com/v3/search/#search-topics """ def __repr__(self): @@ -39,7 +39,6 @@ class Topic(github.GithubObject.CompletableGithubObject): """ :type: string """ - self._completeIfNotSet(self._name) return self._name.value @property @@ -47,7 +46,6 @@ class Topic(github.GithubObject.CompletableGithubObject): """ :type: string """ - self._completeIfNotSet(self._display_name) return self._display_name.value @property @@ -55,7 +53,6 @@ class Topic(github.GithubObject.CompletableGithubObject): """ :type: string """ - self._completeIfNotSet(self._short_description) return self._short_description.value @property @@ -63,14 +60,69 @@ class Topic(github.GithubObject.CompletableGithubObject): """ :type: string """ - self._completeIfNotSet(self._description) return self._description.value + @property + def created_by(self): + """ + :type: string + """ + return self._created_by.value + + @property + def released(self): + """ + :type: string + """ + return self._released.value + + @property + def created_at(self): + """ + :type: datetime.datetime + """ + return self._created_at.value + + @property + def updated_at(self): + """ + :type: datetime.datetime + """ + return self._updated_at.value + + @property + def featured(self): + """ + :type: bool + """ + return self._featured.value + + @property + def curated(self): + """ + :type: bool + """ + return self._curated.value + + @property + def score(self): + """ + :type: float + """ + return self._score.value + def _initAttributes(self): self._name = github.GithubObject.NotSet self._display_name = github.GithubObject.NotSet self._short_description = github.GithubObject.NotSet self._description = github.GithubObject.NotSet + self._created_by = github.GithubObject.NotSet + self._released = github.GithubObject.NotSet + self._created_at = github.GithubObject.NotSet + self._updated_at = github.GithubObject.NotSet + self._featured = github.GithubObject.NotSet + self._curated = github.GithubObject.NotSet + self._score = github.GithubObject.NotSet def _useAttributes(self, attributes): if "name" in attributes: # pragma no branch @@ -81,3 +133,17 @@ class Topic(github.GithubObject.CompletableGithubObject): self._short_description = self._makeStringAttribute(attributes["short_description"]) if "description" in attributes: # pragma no branch self._description = self._makeStringAttribute(attributes["description"]) + if "created_by" in attributes: # pragma no branch + self._created_by = self._makeStringAttribute(attributes["created_by"]) + if "released" in attributes: # pragma no branch + self._released = self._makeStringAttribute(attributes["released"]) + if "created_at" in attributes: # pragma no branch + self._created_at = self._makeDatetimeAttribute(attributes["created_at"]) + if "updated_at" in attributes: # pragma no branch + self._updated_at = self._makeDatetimeAttribute(attributes["updated_at"]) + if "featured" in attributes: # pragma no branch + self._featured = self._makeBoolAttribute(attributes["featured"]) + if "curated" in attributes: # pragma no branch + self._curated = self._makeBoolAttribute(attributes["curated"]) + if "score" in attributes: # pragma no branch + self._score = self._makeFloatAttribute(attributes["score"]) diff --git a/tests/AllTests.py b/tests/AllTests.py index 40de3ddd..3891f06b 100644 --- a/tests/AllTests.py +++ b/tests/AllTests.py @@ -90,6 +90,7 @@ from .RequiredStatusChecks import RequiredStatusChecks from .SourceImport import SourceImport from .Tag import Tag from .Team import Team +from .Topic import Topic from .Traffic import Traffic from .UserKey import UserKey from .Migration import Migration @@ -225,6 +226,7 @@ __all__ = [ SourceImport, Tag, Team, + Topic, Traffic, UserKey, ] diff --git a/tests/ReplayData/Topic.setUp.txt b/tests/ReplayData/Topic.setUp.txt new file mode 100644 index 00000000..92a938a8 --- /dev/null +++ b/tests/ReplayData/Topic.setUp.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/search/topics?q=python +{'Accept': 'application/vnd.github.mercy-preview+json', 'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Wed, 09 Oct 2019 20:35:32 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '200 OK'), ('X-RateLimit-Limit', '10'), ('X-RateLimit-Remaining', '8'), ('X-RateLimit-Reset', '1570653381'), ('Cache-Control', 'no-cache'), ('X-GitHub-Media-Type', 'github.mercy-preview; format=json'), ('Access-Control-Expose-Headers', 'ETag, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '6D0E:2F82:4C1DED:8F5E09:5D9E4493')] +{"total_count":30,"incomplete_results":false,"items":[{"name":"python","display_name":"Python","short_description":"Python is a dynamically typed programming language.","description":"Python is a dynamically typed programming language designed by Guido van Rossum. Much like the programming language Ruby, Python was designed to be easily read by programmers. Because of its large following and many libraries, Python can be implemented and used to do anything from webpages to scientific research.","created_by":"Guido van Rossum","released":"February 20, 1991","created_at":"2016-12-07T00:07:02Z","updated_at":"2019-10-09T20:33:49Z","featured":true,"curated":true,"score":7576.306},{"name":"django","display_name":"Django","short_description":"Django is a web application framework for Python.","description":"Django is a web application framework for Python. It is designed to prioritize principles of reusability and rapid development.","created_by":"Adrian Holovaty, Simon Willison","released":"21 July 2005","created_at":"2017-01-31T20:40:48Z","updated_at":"2019-10-09T20:23:15Z","featured":true,"curated":true,"score":595.4404},{"name":"flask","display_name":"Flask","short_description":"Flask is a web framework for Python based on the Werkzeug toolkit.","description":"Flask is a web framework for Python, based on the Werkzeug toolkit.","created_by":"Armin Ronacher","released":"April 1, 2010","created_at":"2016-12-25T23:31:26Z","updated_at":"2019-10-09T19:46:51Z","featured":true,"curated":true,"score":421.1786},{"name":"python-script","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-01-31T22:02:14Z","updated_at":"2019-10-01T04:14:22Z","featured":false,"curated":false,"score":281.18207},{"name":"python36","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-02-01T23:01:53Z","updated_at":"2019-09-21T01:04:39Z","featured":false,"curated":false,"score":278.21628},{"name":"opencv-python","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-02-03T23:16:55Z","updated_at":"2019-10-05T19:20:25Z","featured":false,"curated":false,"score":277.7204},{"name":"ruby","display_name":"Ruby","short_description":"Ruby is a scripting language designed for simplified object-oriented programming.","description":"Ruby was developed by Yukihiro \"Matz\" Matsumoto in 1995 with the intent of having an easily readable programming language. It is used by the Rails framework to create dynamic web-applications. Ruby's syntax is similar to that of Perl and Python.","created_by":"Yukihiro Matsumoto","released":"December 21, 1995","created_at":"2016-11-28T22:03:59Z","updated_at":"2019-10-09T19:48:54Z","featured":true,"curated":true,"score":275.5379},{"name":"python-library","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-01-31T21:48:51Z","updated_at":"2019-10-08T23:36:08Z","featured":false,"curated":false,"score":261.92603},{"name":"scikit-learn","display_name":"scikit-learn","short_description":"scikit-learn is a Python module for machine learning.","description":"scikit-learn is a widely-used Python module for classic machine learning. It is built on top of SciPy.","created_by":"David Cournapeau","released":"January 05, 2010","created_at":"2017-01-31T21:47:19Z","updated_at":"2019-10-09T19:48:58Z","featured":true,"curated":true,"score":219.94424},{"name":"python37","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-09-23T08:49:36Z","updated_at":"2019-09-21T01:04:46Z","featured":false,"curated":false,"score":193.36407},{"name":"selenium-python","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-06-26T19:02:26Z","updated_at":"2019-09-26T07:00:36Z","featured":false,"curated":false,"score":139.28319},{"name":"sublime-text","display_name":"Sublime Text","short_description":"A cross-platform source code editor with a Python API.","description":"A sophisticated text editor for code, markup and prose.\nIt has many powerful features for file and project navigation, build systems, integration with other tools and customization in the form of plugins, themes, and syntax styles.","created_by":"Jon Skinner, Sublime HQ Pty Ltd","released":"January 18, 2008","created_at":"2017-01-31T21:46:43Z","updated_at":"2019-10-09T18:41:58Z","featured":false,"curated":true,"score":137.15933},{"name":"leetcode-python","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-02-23T02:45:43Z","updated_at":"2019-09-26T07:00:33Z","featured":false,"curated":false,"score":135.47691},{"name":"learning-python","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-01-31T21:48:06Z","updated_at":"2019-09-26T07:00:38Z","featured":false,"curated":false,"score":133.5331},{"name":"tkinter-python","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-12-03T11:05:03Z","updated_at":"2019-09-21T07:52:50Z","featured":false,"curated":false,"score":114.56412},{"name":"python35","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-02-01T23:01:48Z","updated_at":"2019-07-16T10:23:26Z","featured":false,"curated":false,"score":110.58241},{"name":"machinelearning-python","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2018-04-05T05:04:13Z","updated_at":"2019-10-06T06:07:15Z","featured":false,"curated":false,"score":107.01233},{"name":"python-flask","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-02-03T17:08:17Z","updated_at":"2019-09-26T07:00:42Z","featured":false,"curated":false,"score":95.38638},{"name":"python-package","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-02-08T20:03:49Z","updated_at":"2019-10-07T23:32:33Z","featured":false,"curated":false,"score":89.152504},{"name":"python-telegram-bot","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-02-01T10:35:51Z","updated_at":"2019-07-16T10:23:34Z","featured":false,"curated":false,"score":88.10426},{"name":"python-wrapper","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-01-31T23:11:56Z","updated_at":"2019-07-16T10:23:29Z","featured":false,"curated":false,"score":85.25486},{"name":"python3-6","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-04-04T03:37:08Z","updated_at":"2019-07-16T10:23:31Z","featured":false,"curated":false,"score":85.05672},{"name":"opencv3-python","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-05-27T14:02:09Z","updated_at":"2019-09-11T11:41:26Z","featured":false,"curated":false,"score":77.88265},{"name":"hackerrank-python","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-02-03T11:31:38Z","updated_at":"2019-07-16T10:23:37Z","featured":false,"curated":false,"score":77.88265},{"name":"python-api","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-02-01T06:57:54Z","updated_at":"2019-09-19T00:43:28Z","featured":false,"curated":false,"score":76.52807},{"name":"python2-7","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-02-04T21:58:13Z","updated_at":"2019-07-16T10:23:38Z","featured":false,"curated":false,"score":76.32909},{"name":"pythonista","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-01-31T21:45:53Z","updated_at":"2019-09-12T11:21:27Z","featured":false,"curated":false,"score":73.33462},{"name":"haxe","display_name":"Haxe","short_description":"A metalanguage resembling ECMAScript which can be transpiled into a variety of languages.","description":"A language resembling ECMAScript much which can be transpiled into ActionScript3, JavaScript, Java, C++, C#, PHP, Python, and Lua.","created_by":"Nicolas Cannasse, Haxe Foundation","released":"2005","created_at":"2017-01-31T22:12:57Z","updated_at":"2019-09-21T01:01:40Z","featured":false,"curated":true,"score":72.71997},{"name":"python-requests","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-02-03T07:19:24Z","updated_at":"2019-07-16T10:23:43Z","featured":false,"curated":false,"score":71.219284},{"name":"python-2-7","display_name":null,"short_description":null,"description":null,"created_by":null,"released":null,"created_at":"2017-02-02T19:25:09Z","updated_at":"2019-07-16T10:23:40Z","featured":false,"curated":false,"score":71.11855}]} + diff --git a/tests/Topic.py b/tests/Topic.py new file mode 100644 index 00000000..876b04d0 --- /dev/null +++ b/tests/Topic.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- + +############################ Copyrights and license ############################ +# # +# Copyright 2019 Adam Baratz # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +from __future__ import absolute_import + +from datetime import datetime +from operator import attrgetter + +from . import Framework + + +class Topic(Framework.TestCase): + def setUp(self): + Framework.TestCase.setUp(self) + self.topics = list(self.g.search_topics("python")) + + def testAllFields(self): + topic = self.topics[0] + + self.assertEqual(topic.name, "python") + self.assertEqual(topic.display_name, "Python") + self.assertEqual(topic.short_description, "Python is a dynamically typed programming language.") + self.assertEqual(topic.description, "Python is a dynamically typed programming language designed by Guido van Rossum. Much like the programming language Ruby, Python was designed to be easily read by programmers. Because of its large following and many libraries, Python can be implemented and used to do anything from webpages to scientific research.") + self.assertEqual(topic.created_by, "Guido van Rossum") + self.assertEqual(topic.released, "February 20, 1991") + self.assertEqual(topic.created_at, datetime(2016, 12, 7, 0, 7, 2)) + self.assertEqual(topic.updated_at, datetime(2019, 10, 9, 20, 33, 49)) + self.assertEqual(topic.featured, True) + self.assertEqual(topic.curated, True) + self.assertEqual(topic.score, 7576.306) + + self.assertEqual(topic.__repr__(), u'Topic(name="python")') + + def testNamesFromSearchResults(self): + expected_names = [ + 'python', + 'django', + 'flask', + 'python-script', + 'python36', + 'opencv-python', + 'ruby', + 'python-library', + 'scikit-learn', + 'python37', + 'selenium-python', + 'sublime-text', + 'leetcode-python', + 'learning-python', + 'tkinter-python', + 'python35', + 'machinelearning-python', + 'python-flask', + 'python-package', + 'python-telegram-bot', + 'python-wrapper', + 'python3-6', + 'opencv3-python', + 'hackerrank-python', + 'python-api', + 'python2-7', + 'pythonista', + 'haxe', + 'python-requests', + 'python-2-7', + ] + + self.assertListKeyEqual(self.topics, attrgetter("name"), expected_names)