From e22773c82e0ce9b61c92a32f1b1711c56f743bb2 Mon Sep 17 00:00:00 2001 From: Asif Mallik Date: Tue, 25 Aug 2020 18:38:34 -0400 Subject: [PATCH 01/13] Implement sniff_mislabeled_feed --- sniffpy/constants.py | 4 ++ sniffpy/sniff.py | 92 ++++++++++++++++++++++++++++++++++++++++-- sniffpy/terminology.py | 2 + 3 files changed, 95 insertions(+), 3 deletions(-) diff --git a/sniffpy/constants.py b/sniffpy/constants.py index 762f7a4..b32c604 100644 --- a/sniffpy/constants.py +++ b/sniffpy/constants.py @@ -4,6 +4,10 @@ # pylint: disable=line-too-long from sniffpy.mimetype import MIMEType +# URLs +RSS_PURL_URL = b'http://purl.org/rss/1.0/' +RDF_SYNTAX_URL = b'http://www.w3.org/1999/02/22-rdf-syntax-ns#' + # Bytes that the specification defines as whitespace WHITESPACE = b'\x09\x0a\x0c\x0d\x20' UNDEFINED = MIMEType('undefined', 'undefined') diff --git a/sniffpy/sniff.py b/sniffpy/sniff.py index f8b885b..2fa657b 100644 --- a/sniffpy/sniff.py +++ b/sniffpy/sniff.py @@ -4,6 +4,56 @@ from . import terminology from . import constants as const +def skip_comment(sequence: bytes, i: int, length: int) -> (int, bool): + if i + 3 <= length and sequence[i:i+3] == b'!--': + i += 3 + while i < length: + if i + 3 <= 3 and sequence[i:i+3] == b'-->': + i += 3 + return i, True + i += 1 + return i, False + +def skip_markup_declaration(sequence: bytes, i: int, length: int) -> (int, bool): + if i + 1 <= length and sequence[i:i+1] == b'!': #RHS is internally an array of integer + i += 1 + while i < length: + if i + 1 <= length and sequence[i:i+1] == b'>': + i += 1 + return i, True + i += 1 + return i, False + +def skip_processing_instruction(sequence: bytes, i: int, length: int) -> (int, bool): + if i + 1 <= length and sequence[i:i+1] == b'?': #RHS is internally an array of integers + i += 1 + while i < length: + if i + 2 <= length and sequence[i:i+2] == b'?>': + i += 2 + return i, True + i += 1 + return i, False + +def handle_rdf(sequence: bytes, i: int, length: int) -> (int, MIMEType): + if i + 7 <= length and sequence[i:i+7] == b'rdf:RDF': + i += 7 + while i < length: + if i + 24 <= length and sequence[i:i+24] == const.RSS_PURL_URL: + i += 24 + while i < length: + if i + 43 <= length and sequence[i:i+43] == const.RDF_SYNTAX_URL: + return i, MIMEType("application", "rss+xml") + i += 1 + if i + 43 <= length and sequence[i:i+43] == const.RDF_SYNTAX_URL: + i += 43 + while i < length: + if i + 24 <= length and sequence[i:i+24] == const.RSS_PURL_URL: + return i, MIMEType("application", "rss+xml") + i += 1 + i += 1 + i += 1 #TODO: incorporate response to https://github.com/whatwg/mimesniff/issues/127 + return i, None + def sniff_unknown(resource: bytes, sniff_scriptable: bool = False) -> MIMEType: # might need more arguments if sniff_scriptable: @@ -49,8 +99,44 @@ def sniff_mislabeled_binary(resource: bytes) -> MIMEType: return MIMEType("application", "octet-stream") -def sniff_mislabeled_feed(resource: bytes) -> MIMEType: - raise NotImplementedError +def sniff_mislabeled_feed(sequence: bytes, supplied_mime_type: MIMEType) -> MIMEType: + length = len(sequence) + i = 0 + if length >= 3 and sequence[:3] == b'\xef\xbb\xbf': + i += 3 + while i < length: + while i < length: + if sequence[i:i+1] == b'<': #RHS is internally an array of integers + i += 1 + break + if not terminology.is_white_space_byte(sequence[i:i+1]): + return supplied_mime_type + i += 1 + + while i < length: + i, break_outer_loop = skip_comment(sequence, i, length) + if break_outer_loop: + break + + i, break_outer_loop = skip_markup_declaration(sequence, i, length) + if break_outer_loop: + break + + i, break_outer_loop = skip_processing_instruction(sequence, i, length) + if break_outer_loop: + break + + if i + 3 <= length and sequence[i:i+3] == b'rss': + return MIMEType("application", "rss+xml") + + if i + 4 <= length and sequence[i:i+4] == b'feed': + return MIMEType("application", "atom+xml") + + i, mime_type = handle_rdf(sequence, i, length) + if mime_type is not None: + return mime_type + + return supplied_mime_type def sniff( @@ -68,7 +154,7 @@ def sniff( if mime_type.is_xml(): return mime_type if mime_type.essence() == "text/html": - sniff_mislabeled_feed(resource) + return sniff_mislabeled_feed(resource, mime_type) if mime_type.is_image(): # TODO: implement checking suppported image by user agent match_type = match.match_image_type_pattern(resource) if match_type is not None: diff --git a/sniffpy/terminology.py b/sniffpy/terminology.py index 932af7b..d499609 100644 --- a/sniffpy/terminology.py +++ b/sniffpy/terminology.py @@ -1,5 +1,7 @@ import re +def is_white_space_byte(byte: bytes) -> bool: + return byte in (b'\x09', b'\x0a', b'\x0c', b'\x0d', b'\x20') def contains_binary_bytes(resource: bytes) -> bool: contains_binary = False From 8b0e9709174778eea607fc8a6ff4e3250111ddb0 Mon Sep 17 00:00:00 2001 From: Asif Mallik Date: Tue, 25 Aug 2020 18:52:52 -0400 Subject: [PATCH 02/13] Document helper function code --- sniffpy/sniff.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/sniffpy/sniff.py b/sniffpy/sniff.py index 2fa657b..c5c87aa 100644 --- a/sniffpy/sniff.py +++ b/sniffpy/sniff.py @@ -4,7 +4,14 @@ from . import terminology from . import constants as const +#The following functions are helper functions for sniff_mislabeled_feed +#TODO: Rewrite the skip_* functions into one single neat parameterized function def skip_comment(sequence: bytes, i: int, length: int) -> (int, bool): + """ + Skips XML in the sequence (resource) + They are in the form + """ + if i + 3 <= length and sequence[i:i+3] == b'!--': i += 3 while i < length: @@ -15,6 +22,11 @@ def skip_comment(sequence: bytes, i: int, length: int) -> (int, bool): return i, False def skip_markup_declaration(sequence: bytes, i: int, length: int) -> (int, bool): + """ + Skips XML markup declarations in the sequence (resource) + in the form + """ + if i + 1 <= length and sequence[i:i+1] == b'!': #RHS is internally an array of integer i += 1 while i < length: @@ -25,6 +37,11 @@ def skip_markup_declaration(sequence: bytes, i: int, length: int) -> (int, bool) return i, False def skip_processing_instruction(sequence: bytes, i: int, length: int) -> (int, bool): + """ + Skips XML processing instruction in the sequence (resource) + They are in the form + """ + if i + 1 <= length and sequence[i:i+1] == b'?': #RHS is internally an array of integers i += 1 while i < length: @@ -35,6 +52,12 @@ def skip_processing_instruction(sequence: bytes, i: int, length: int) -> (int, b return i, False def handle_rdf(sequence: bytes, i: int, length: int) -> (int, MIMEType): + """ + Handles Resource Description Framework + First checks whether it is an RDF + If so, then it verifies whether it is an RSS and returns the MIME type accordingly + """ + if i + 7 <= length and sequence[i:i+7] == b'rdf:RDF': i += 7 while i < length: @@ -54,6 +77,7 @@ def handle_rdf(sequence: bytes, i: int, length: int) -> (int, MIMEType): i += 1 #TODO: incorporate response to https://github.com/whatwg/mimesniff/issues/127 return i, None +#Functions from specification section 7 def sniff_unknown(resource: bytes, sniff_scriptable: bool = False) -> MIMEType: # might need more arguments if sniff_scriptable: @@ -138,7 +162,6 @@ def sniff_mislabeled_feed(sequence: bytes, supplied_mime_type: MIMEType) -> MIME return supplied_mime_type - def sniff( resource: bytes, mime_type_string: str = "unknown/unknown", From 381dcc4f4a2c06c69de22347c71f6c176614c753 Mon Sep 17 00:00:00 2001 From: Asif Mallik Date: Tue, 25 Aug 2020 18:53:41 -0400 Subject: [PATCH 03/13] Styling fixes --- sniffpy/sniff.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sniffpy/sniff.py b/sniffpy/sniff.py index c5c87aa..7df5c59 100644 --- a/sniffpy/sniff.py +++ b/sniffpy/sniff.py @@ -8,10 +8,10 @@ #TODO: Rewrite the skip_* functions into one single neat parameterized function def skip_comment(sequence: bytes, i: int, length: int) -> (int, bool): """ - Skips XML in the sequence (resource) + Skips XML in the sequence (resource) They are in the form """ - + if i + 3 <= length and sequence[i:i+3] == b'!--': i += 3 while i < length: From bce8fcb046944fffd7f803e075f27b89f15fc831 Mon Sep 17 00:00:00 2001 From: Asif Mallik Date: Fri, 28 Aug 2020 22:42:39 -0400 Subject: [PATCH 04/13] Fix small typo --- sniffpy/match.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sniffpy/match.py b/sniffpy/match.py index bc81849..4bb4f99 100644 --- a/sniffpy/match.py +++ b/sniffpy/match.py @@ -16,7 +16,7 @@ def match_pattern( mask: bytes, ignored: bytes): """ - Implementation of algorithm in:x + Implementation of algorithm in: https://mimesniff.spec.whatwg.org/#matching-a-mime-type-pattern True if pattern matches the resource. False otherwise. """ From c0baf12084f6a0115094a379bf6659847f7710e2 Mon Sep 17 00:00:00 2001 From: Asif Mallik Date: Fri, 28 Aug 2020 23:09:23 -0400 Subject: [PATCH 05/13] Document section 7 --- sniffpy/sniff.py | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/sniffpy/sniff.py b/sniffpy/sniff.py index 7df5c59..48c9f80 100644 --- a/sniffpy/sniff.py +++ b/sniffpy/sniff.py @@ -11,7 +11,7 @@ def skip_comment(sequence: bytes, i: int, length: int) -> (int, bool): Skips XML in the sequence (resource) They are in the form """ - + if i + 3 <= length and sequence[i:i+3] == b'!--': i += 3 while i < length: @@ -79,6 +79,15 @@ def handle_rdf(sequence: bytes, i: int, length: int) -> (int, MIMEType): #Functions from specification section 7 def sniff_unknown(resource: bytes, sniff_scriptable: bool = False) -> MIMEType: + """ + Implementation of algorithm in: + https://mimesniff.spec.whatwg.org/#identifying-a-resource-with-an-unknown-mime-type + + Given a resource, it tries to sniff its MIME type. The sniff_scriptable argument + indicates whether it should sniff for scriptable MIME types which is defined as + any MIME type whose essence is "application/pdf" + """ + # might need more arguments if sniff_scriptable: mime_type = match.match_pattern_from_table(resource, const.UNKNOWN_PATTERNS) @@ -108,6 +117,14 @@ def sniff_unknown(resource: bytes, sniff_scriptable: bool = False) -> MIMEType: return MIMEType("application", "octet-stream") def sniff_mislabeled_binary(resource: bytes) -> MIMEType: + """ + Implementation of algorithm in: + https://mimesniff.spec.whatwg.org/#sniffing-a-mislabeled-binary-resource + + Determines whether a given resource has been mislabeled + as plain text and returns the corrected MIME type + """ + plaintext_mimetype = MIMEType("text", "plain") length = len(resource) @@ -124,6 +141,14 @@ def sniff_mislabeled_binary(resource: bytes) -> MIMEType: return MIMEType("application", "octet-stream") def sniff_mislabeled_feed(sequence: bytes, supplied_mime_type: MIMEType) -> MIMEType: + """ + Implementation of algorithm in: + https://mimesniff.spec.whatwg.org/#sniffing-a-mislabeled-feed + + Determines whether a feed has been mislabeled as HTML and returns + the corrected MIME type (RSS, Atom or HTML) + """ + length = len(sequence) i = 0 if length >= 3 and sequence[:3] == b'\xef\xbb\xbf': @@ -167,6 +192,15 @@ def sniff( mime_type_string: str = "unknown/unknown", no_sniff: bool = False, check_for_apache_bug: bool = False) -> str: + """ + Implementation of algorithm in: + https://mimesniff.spec.whatwg.org/#determining-the-computed-mime-type-of-a-resource + + The main method that will be called by users to determine the MIME type of a + resource. The mime_type_string indicates the supplied MIME type (for example, in the + case of HTTP would be the Content-Type). + """ + mime_type = mimetype.parse_mime_type(mime_type_string) if mime_type.is_unknown(): return sniff_unknown(resource, sniff_scriptable=not no_sniff) From f7bf139328c11418f5b1377ff1c36f934495db86 Mon Sep 17 00:00:00 2001 From: Asif Mallik Date: Sat, 29 Aug 2020 05:19:39 -0400 Subject: [PATCH 06/13] Add documentation for section 3 and 4 --- sniffpy/mimetype.py | 38 ++++++++++++++++++++++++++++++++++---- sniffpy/terminology.py | 6 ++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/sniffpy/mimetype.py b/sniffpy/mimetype.py index 63572e0..f98b80e 100644 --- a/sniffpy/mimetype.py +++ b/sniffpy/mimetype.py @@ -1,12 +1,34 @@ +""" +Implementation of section 4 in the specification: +https://mimesniff.spec.whatwg.org/#understanding-mime-types + +Contains the MIMEType class definition and an implementation +of MIME type parsing. +""" + from . import ref from . import terminology - class MIMEType: - """ TODO: Add class docstring""" + """ + This class defines a MIME type and has as its methods + and properties, definitions and algorithms from + section 4 of the specification. + """ def __init__(self, _type: str, _subtype: str, parameters: dict = None) -> None: + """ + This initializes a MIME type. + + * type: the general category into which a resource falls under, + for example, "text" + * subtype: the exact category of the specific type, for example, + "plain" + * parameters: a string to string mapping containing + further information of the MIME type, for example, {"charset": "UTF-8"} + """ + self.type = _type self.subtype = _subtype if parameters is None: @@ -17,8 +39,8 @@ def __init__(self, _type: str, _subtype: str, def essence(self) -> str: return self.type + "/" + self.subtype - def __str__(self) -> str: - return self.type + "/" + self.subtype # TODO: Implement parameter + def __str__(self) -> str: #TODO: Should be an implementation of 4.5 + return self.type + "/" + self.subtype def is_xml(self) -> bool: if len(self.subtype) > 3 and self.subtype[-4:] == "+xml": @@ -44,6 +66,14 @@ def __eq__(self, obj): return value def parse_mime_type(str_input: str) -> MIMEType: + """ + Implementation of algorithm in: + https://mimesniff.spec.whatwg.org/#parsing-a-mime-type + + Given a string representation of a MIME type this function + parses it and returns its representation as an instance of MIMEType + """ + str_input = str_input.strip() # might have to specify HTTP whitespace characters pos = 0 _type, pos = ref.collect_code_points(str_input, ['/'], pos) diff --git a/sniffpy/terminology.py b/sniffpy/terminology.py index d499609..c8221a0 100644 --- a/sniffpy/terminology.py +++ b/sniffpy/terminology.py @@ -1,9 +1,15 @@ +""" +This module contains the definitions from section 3 in the specification: +https://mimesniff.spec.whatwg.org/#terminology +""" + import re def is_white_space_byte(byte: bytes) -> bool: return byte in (b'\x09', b'\x0a', b'\x0c', b'\x0d', b'\x20') def contains_binary_bytes(resource: bytes) -> bool: + contains_binary = False for byte in resource: From a76dc4a40210554484ec1ab4f470fd15a04a7241 Mon Sep 17 00:00:00 2001 From: Asif Mallik Date: Tue, 1 Sep 2020 11:44:50 -0400 Subject: [PATCH 07/13] Add example in README --- README.rst | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 7be28f1..aa764f7 100644 --- a/README.rst +++ b/README.rst @@ -1,9 +1,36 @@ ======================================= Sniffpy ======================================= -A python implementation of ``_ -Documentation on how to use the package and how to contribute can be found -on ``_ +Sniffpy is a python implementation of `MIME Sniffing Standard `_ +MIME sniffing describes algorithms that attempt to discern the correct MIME type of some given +data. The MIME type of a file or byte stream describes its format. For example, the MIME type of an image could be +`image/jpeg` or `image/png` depending on its exact format. MIME types consist of: + +* the `type` which describesthe broad category of the data +* the `subtype` which describes the exact kind of data +* an optional `parameter` which gives further information about the data + +The exact specification of MIME types can be found `here `_ + +Example +--------------- +The following is an example on how to use sniffpy to guess the MIME type of an HTTP response using requests + +``` +import sniffpy +import requests + +r = requests.get("https://httpbin.org/image/jpeg") +mime_type = sniffpy.sniff(r.content) #returns a MIMEType object -WARNING: This project is still being implemented and shouldn't be used yet. +print(mime_type.type) #prints "image" +print(mime_type.subtype) #prints "jpeg" + +print(mime_type) #prints "image/jpeg" + +``` + + +Documentation on how to use the package and how to contribute can be found +on ``_ From b17e07862d64d4ec2335fb9d1ac4cc9673d11ccc Mon Sep 17 00:00:00 2001 From: Asif Mallik Date: Tue, 1 Sep 2020 11:54:56 -0400 Subject: [PATCH 08/13] Include code properly --- README.rst | 17 ++--------------- example.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 15 deletions(-) create mode 100644 example.py diff --git a/README.rst b/README.rst index aa764f7..823a2c6 100644 --- a/README.rst +++ b/README.rst @@ -17,20 +17,7 @@ Example --------------- The following is an example on how to use sniffpy to guess the MIME type of an HTTP response using requests -``` -import sniffpy -import requests - -r = requests.get("https://httpbin.org/image/jpeg") -mime_type = sniffpy.sniff(r.content) #returns a MIMEType object - -print(mime_type.type) #prints "image" -print(mime_type.subtype) #prints "jpeg" - -print(mime_type) #prints "image/jpeg" - -``` - - +.. literalinclude:: example.py + :language: python Documentation on how to use the package and how to contribute can be found on ``_ diff --git a/example.py b/example.py new file mode 100644 index 0000000..883723d --- /dev/null +++ b/example.py @@ -0,0 +1,10 @@ +import sniffpy +import requests + +r = requests.get("https://httpbin.org/image/jpeg") +mime_type = sniffpy.sniff(r.content) #returns a MIMEType object + +print(mime_type.type) #prints "image" +print(mime_type.subtype) #prints "jpeg" + +print(mime_type) #prints "image/jpeg" From 961818ad7636e6135fbef40333aa51ac2bca30d9 Mon Sep 17 00:00:00 2001 From: Asif Mallik Date: Tue, 1 Sep 2020 12:00:37 -0400 Subject: [PATCH 09/13] Use codeblock instead --- README.rst | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 823a2c6..e982b9b 100644 --- a/README.rst +++ b/README.rst @@ -17,7 +17,16 @@ Example --------------- The following is an example on how to use sniffpy to guess the MIME type of an HTTP response using requests -.. literalinclude:: example.py - :language: python +.. codeblock:: python + import requests + + r = requests.get("https://httpbin.org/image/jpeg") + mime_type = sniffpy.sniff(r.content) #returns a MIMEType object + + print(mime_type.type) #prints "image" + print(mime_type.subtype) #prints "jpeg" + + print(mime_type) #prints "image/jpeg" + Documentation on how to use the package and how to contribute can be found on ``_ From 17d4dbd6c6bdbcbd3997833b89248a5e6e054da4 Mon Sep 17 00:00:00 2001 From: Asif Mallik Date: Tue, 1 Sep 2020 12:42:39 -0400 Subject: [PATCH 10/13] Switch from rst to md --- README.md | 30 ++++++++++++++++++++++++++++++ README.rst | 32 -------------------------------- 2 files changed, 30 insertions(+), 32 deletions(-) create mode 100644 README.md delete mode 100644 README.rst diff --git a/README.md b/README.md new file mode 100644 index 0000000..4e3c57b --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# Sniffpy + +Sniffpy is a python implementation of [MIME Sniffing Standard](https://mimesniff.specw.whatwg.org/) +MIME sniffing describes algorithms that attempt to discern the correct MIME type of some given +data. The MIME type of a file or byte stream describes its format. For example, the MIME type of an image could be +`image/jpeg` or `image/png` depending on its exact format. MIME types consist of: + +* the `type` which describesthe broad category of the data +* the `subtype` which describes the exact kind of data +* an optional `parameter` which gives further information about the data + +The exact specification of MIME types can be found [here](https://tools.ietf.org/html/rfc6838) + +## Example + +The following is an example on how to use sniffpy to guess the MIME type of an HTTP response using requests + +``` +import requests + +r = requests.get("https://httpbin.org/image/jpeg") +mime_type = sniffpy.sniff(r.content) #returns a MIMEType object + +print(mime_type.type) #prints "image" +print(mime_type.subtype) #prints "jpeg" + +print(mime_type) #prints "image/jpeg" +``` + +Documentation on how to use the package and how to contribute can be found on [here](https://sniffpy.readthedocs.io/en/latest/) diff --git a/README.rst b/README.rst deleted file mode 100644 index e982b9b..0000000 --- a/README.rst +++ /dev/null @@ -1,32 +0,0 @@ -======================================= -Sniffpy -======================================= - -Sniffpy is a python implementation of `MIME Sniffing Standard `_ -MIME sniffing describes algorithms that attempt to discern the correct MIME type of some given -data. The MIME type of a file or byte stream describes its format. For example, the MIME type of an image could be -`image/jpeg` or `image/png` depending on its exact format. MIME types consist of: - -* the `type` which describesthe broad category of the data -* the `subtype` which describes the exact kind of data -* an optional `parameter` which gives further information about the data - -The exact specification of MIME types can be found `here `_ - -Example ---------------- -The following is an example on how to use sniffpy to guess the MIME type of an HTTP response using requests - -.. codeblock:: python - import requests - - r = requests.get("https://httpbin.org/image/jpeg") - mime_type = sniffpy.sniff(r.content) #returns a MIMEType object - - print(mime_type.type) #prints "image" - print(mime_type.subtype) #prints "jpeg" - - print(mime_type) #prints "image/jpeg" - -Documentation on how to use the package and how to contribute can be found -on ``_ From 2d3d9d9755611e71d2cde5d8aba408f0dcff8111 Mon Sep 17 00:00:00 2001 From: Asif Mallik Date: Tue, 1 Sep 2020 12:49:17 -0400 Subject: [PATCH 11/13] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 249f5e7..3af5175 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ import setuptools -with open("README.rst", "r") as fh: +with open("README.md", "r") as fh: long_description = fh.read() setuptools.setup( From 497d63a1594d32a2ba35d78ff7c4a44107805733 Mon Sep 17 00:00:00 2001 From: Devin Leamy Date: Wed, 30 Sep 2020 14:12:49 -0400 Subject: [PATCH 12/13] Changed make commands to match Makefile --- docs/source/contributing.rst | 40 ++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/docs/source/contributing.rst b/docs/source/contributing.rst index cdc86e1..87cbeaf 100644 --- a/docs/source/contributing.rst +++ b/docs/source/contributing.rst @@ -6,23 +6,23 @@ Contributing to Sniffpy Thank you for deciding to contribute to Sniffpy. We welcome contributors of all levels of expertise and are willing to provide guidance when needed. This document outlines the steps to take to contribute and some general guidelines -and rules about the project. +and rules about the project. * `Setting up the development environment`_ * `Contributing with code`_ * `Contributing with documentation`_ - + .. warning:: Sniffpy uses Git and Github extensively. Throughout, we will assume that you are familiar with these tools. However, if you are not not or there are concepts you need a refresher for, `this guide `_ is an - excellent resource. + excellent resource. -------------------------------------------- +------------------------------------------- Setting up the development environment -------------------------------------------- +------------------------------------------- Regardless of whether you are contributing to code or documentation you need to set up an environment in you computer. If you know how to do this you can skip @@ -40,9 +40,9 @@ button on the top right of the page that allows you to do this.) Once the repository is forked you need to get a copy of it in your computer. There are various ways of doing this. One such way is to navigate from your terminal to the folder you'd like the project to be in and type: :: - + git clone https://github.com//sniffpy.git - + Doing this should create a directory on your computer with the project inside of it. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ dependencies inside of it. If you are a Windows user you will need to first install GNU make. We recommend that to do this you install the package manager `Chocolatey `_ and then from the command line or powershell run: :: - + choco install make If everything is working properly you should be able to use the make commands @@ -80,7 +80,7 @@ Using your virtual Environment ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ To use your virtual environment you should go the root directory and from the command line type :: - + source venv/bin/activate if you are using Mac or Linux, or:: @@ -91,7 +91,7 @@ if you are using Windows. To leave your virtual environment type:: deactivate - + Remember to always use your virtual environment when testing or modifying documents or code. @@ -105,7 +105,7 @@ Contributing with code To make changes to your repository create a new branch. **NEVER** user the Master branch. A new branch can be easily created by going inside of the project directory and issuing the command:: - + git checkout -b where ```` should be replaced by some name reflective of the changes you @@ -121,8 +121,8 @@ and which are neccesary for any code sumbission to be accepted. * **PEP8**: All the code that you write should follow the PEP8 style guide. To make sure that you comply with this standard you should run :: - - make checkstyle + + make stylecheck from the code root directory. Running ``make checkstyle`` should return no error. Code that doesn't apply PEP8 **won't** be incorparated in the repo. If you @@ -151,37 +151,33 @@ and which are neccesary for any code sumbission to be accepted. `pytest documentation `_ to get familiar with it. Before, any pull-request you should run the command :: - make tests + make test from the root directory to make sure that all the tests pass. Only code where all the tests pass will be accepted. Nevertheless, don't hesitate to ask for help from the mantainers when needed. - + ^^^^^^^^^^^^^^^^^^^^^^ Making a Pull Request ^^^^^^^^^^^^^^^^^^^^^^ Once you have fixed the issue and have committed all your changes you should run:: - + make push from the root of the project directory. This will run all the tests and will check that your code follows the PEP8 guidelines. Fix the problems in your code and re-run ``make push`` till all tests pass. Once all the tests pass run the command :: - + git push and then direct yourself to your forked copy of the repo on GitHub. From there you will be -able to make a pull request with your changes. +able to make a pull request with your changes. -------------------------------- Contributing with documentation -------------------------------- - - - - From 4ff6838d40a83f9c3a3085a70e5e034dea284e8e Mon Sep 17 00:00:00 2001 From: Devin Leamy Date: Wed, 30 Sep 2020 16:52:24 -0400 Subject: [PATCH 13/13] Changed make checkstyle to make stylecheck --- docs/source/contributing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/contributing.rst b/docs/source/contributing.rst index 87cbeaf..e90ea98 100644 --- a/docs/source/contributing.rst +++ b/docs/source/contributing.rst @@ -124,7 +124,7 @@ and which are neccesary for any code sumbission to be accepted. make stylecheck - from the code root directory. Running ``make checkstyle`` should return no error. + from the code root directory. Running ``make stylecheck`` should return no error. Code that doesn't apply PEP8 **won't** be incorparated in the repo. If you are not familiar with PEP8 you can read about it in `PEP 8 `_.