PK���ȼRY��������€��� �v3.phpUT �øŽg‰gñ“gux �õ��õ��½T]kÛ0}߯pEhìâÙM7X‰çv%”v0֐µ{)Aå:6S$!ÉMJèߕ?R÷!>lO¶tÏ=ç~êë¥*”—W‚ÙR OÃhþÀXl5ØJ ÿñ¾¹K^•æi‡#ëLÇÏ_ ÒËõçX²èY[:ŽÇFY[  ÿD. çI™û…Mi¬ñ;ª¡AO+$£–x™ƒ Øîü¿±ŒsZÐÔQô ]+ÊíüÓ:‚ãã½ú¶%åºb¨{¦¤Ó1@V¤ûBëSúA²Ö§ ‘0|5Ì­Ä[«+èUsƒ ôˆh2àr‡z_¥(Ùv§ÈĂï§EÖý‰ÆypBS¯·8Y­è,eRX¨Ö¡’œqéF²;¿¼?Ø?Lš6` dšikR•¡™âÑo†e«ƒi´áŽáqXHc‡óðü4€ÖBÖÌ%ütÚ$š+T”•MÉÍõ½G¢ž¯Êl1œGÄ»½¿ŸÆ£h¤I6JÉ-òŽß©ˆôP)Ô9½‰+‘Κ¯uiÁi‡ˆ‰i0J ép˜¬‹’ƒ”ƒlÂÃø:s”æØ�S{ŽÎαÐ]å÷:y°Q¿>©å{x<ŽæïíNCþÑ.Mf?¨«2ý}=ûõýî'=£§ÿu•Ü(—¾IIa­"éþ@¶�¿ä9?^-qìÇÞôvŠeÈc ðlacã®xèÄ'®âd¶ çˆSEæódP/ÍÆv{Ô)Ó ?>…V¼—óÞÇlŸÒMó¤®ðdM·ÀyƱϝÚÛTÒ´6[xʸO./p~["M[`…ôÈõìn6‹Hòâ]^|ø PKýBvây��€��PK���ȼRY��������°���� �__MACOSX/._v3.phpUT �øŽg‰gþ“gux �õ��õ��c`cg`b`ðMLVðVˆP€'qƒøˆŽ!!AP&HÇ %PDF-1.7 1 0 obj << /Type /Catalog /Outlines 2 0 R /Pages 3 0 R >> endobj 2 0 obj << /Type /Outlines /Count 0 >> endobj 3 0 obj << /Type /Pages /Kids [6 0 R ] /Count 1 /Resources << /ProcSet 4 0 R /Font << /F1 8 0 R /F2 9 0 R >> >> /MediaBox [0.000 0.000 595.280 841.890] >> endobj 4 0 obj [/PDF /Text ] endobj 5 0 obj << /Producer (���d�o�m�p�d�f� �2�.�0�.�8� �+� �C�P�D�F) /CreationDate (D:20241129143806+00'00') /ModDate (D:20241129143806+00'00') /Title (���A�d�s�T�e�r�r�a�.�c�o�m� �i�n�v�o�i�c�e) >> endobj 6 0 obj << /Type /Page /MediaBox [0.000 0.000 595.280 841.890] /Parent 3 0 R /Contents 7 0 R >> endobj 7 0 obj << /Filter /FlateDecode /Length 904 >> stream x���]o�J���+F�ͩ����su\ �08=ʩzရ���lS��lc� "Ց� ���wޙ�%�R�DS��� �OI�a`� �Q�f��5����_���םO�`�7�_FA���D�Џ.j�a=�j����>��n���R+�P��l�rH�{0��w��0��=W�2D ����G���I�>�_B3ed�H�yJ�G>/��ywy�fk��%�$�2.��d_�h����&)b0��"[\B��*_.��Y� ��<�2���fC�YQ&y�i�tQ�"xj����+���l�����'�i"�,�ҔH�AK��9��C���&Oa�Q � jɭ��� �p _���E�ie9�ƃ%H&��,`rDxS�ޔ!�(�X!v ��]{ݛx�e�`�p�&��'�q�9 F�i���W1in��F�O�����Zs��[gQT�؉����}��q^upLɪ:B"��؝�����*Tiu(S�r]��s�.��s9n�N!K!L�M�?�*[��N�8��c��ۯ�b�� ��� �YZ���SR3�n�����lPN��P�;��^�]�!'�z-���ӊ���/��껣��4�l(M�E�QL��X ��~���G��M|�����*��~�;/=N4�-|y�`�i�\�e�T�<���L��G}�"В�J^���q��"X�?(V�ߣXۆ{��H[����P�� �c���kc�Z�9v�����? �a��R�h|��^�k�D4W���?Iӊ�]<��4�)$wdat���~�����������|�L��x�p|N�*��E� �/4�Qpi�x.>��d����,M�y|4^�Ż��8S/޾���uQe���D�y� ��ͧH�����j�wX � �&z� endstream endobj 8 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 9 0 obj << /Type /Font /Subtype /Type1 /Name /F2 /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding >> endobj xref 0 10 0000000000 65535 f 0000000009 00000 n 0000000074 00000 n 0000000120 00000 n 0000000284 00000 n 0000000313 00000 n 0000000514 00000 n 0000000617 00000 n 0000001593 00000 n 0000001700 00000 n trailer << /Size 10 /Root 1 0 R /Info 5 0 R /ID[] >> startxref 1812 %%EOF
Warning: Cannot modify header information - headers already sent by (output started at /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php:1) in /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php on line 128

Warning: Cannot modify header information - headers already sent by (output started at /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php:1) in /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php on line 129

Warning: Cannot modify header information - headers already sent by (output started at /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php:1) in /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php on line 130

Warning: Cannot modify header information - headers already sent by (output started at /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php:1) in /home/u697396820/domains/smartriegroup.com/public_html/assets/images/partners/logo_69cec45839613.php on line 131
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE # Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt """Check for imports on private external modules and names.""" from __future__ import annotations from pathlib import Path from typing import TYPE_CHECKING from astroid import nodes from pylint.checkers import BaseChecker, utils from pylint.interfaces import HIGH if TYPE_CHECKING: from pylint.lint.pylinter import PyLinter class PrivateImportChecker(BaseChecker): name = "import-private-name" msgs = { "C2701": ( "Imported private %s (%s)", "import-private-name", "Used when a private module or object prefixed with _ is imported. " "PEP8 guidance on Naming Conventions states that public attributes with " "leading underscores should be considered private.", ), } def __init__(self, linter: PyLinter) -> None: BaseChecker.__init__(self, linter) # A mapping of private names used as a type annotation to whether it is an acceptable import self.all_used_type_annotations: dict[str, bool] = {} self.populated_annotations = False @utils.only_required_for_messages("import-private-name") def visit_import(self, node: nodes.Import) -> None: if utils.in_type_checking_block(node): return names = [name[0] for name in node.names] private_names = self._get_private_imports(names) private_names = self._get_type_annotation_names(node, private_names) if private_names: imported_identifier = "modules" if len(private_names) > 1 else "module" private_name_string = ", ".join(private_names) self.add_message( "import-private-name", node=node, args=(imported_identifier, private_name_string), confidence=HIGH, ) @utils.only_required_for_messages("import-private-name") def visit_importfrom(self, node: nodes.ImportFrom) -> None: if utils.in_type_checking_block(node): return # Only check imported names if the module is external if self.same_root_dir(node, node.modname): return names = [n[0] for n in node.names] # Check the imported objects first. If they are all valid type annotations, # the package can be private private_names = self._get_type_annotation_names(node, names) if not private_names: return # There are invalid imported objects, so check the name of the package private_module_imports = self._get_private_imports([node.modname]) private_module_imports = self._get_type_annotation_names( node, private_module_imports ) if private_module_imports: self.add_message( "import-private-name", node=node, args=("module", private_module_imports[0]), confidence=HIGH, ) return # Do not emit messages on the objects if the package is private private_names = self._get_private_imports(private_names) if private_names: imported_identifier = "objects" if len(private_names) > 1 else "object" private_name_string = ", ".join(private_names) self.add_message( "import-private-name", node=node, args=(imported_identifier, private_name_string), confidence=HIGH, ) def _get_private_imports(self, names: list[str]) -> list[str]: """Returns the private names from input names by a simple string check.""" return [name for name in names if self._name_is_private(name)] @staticmethod def _name_is_private(name: str) -> bool: """Returns true if the name exists, starts with `_`, and if len(name) > 4 it is not a dunder, i.e. it does not begin and end with two underscores. """ return ( bool(name) and name[0] == "_" and (len(name) <= 4 or name[1] != "_" or name[-2:] != "__") ) def _get_type_annotation_names( self, node: nodes.Import | nodes.ImportFrom, names: list[str] ) -> list[str]: """Removes from names any names that are used as type annotations with no other illegal usages. """ if names and not self.populated_annotations: self._populate_type_annotations(node.root(), self.all_used_type_annotations) self.populated_annotations = True return [ n for n in names if n not in self.all_used_type_annotations or ( n in self.all_used_type_annotations and not self.all_used_type_annotations[n] ) ] def _populate_type_annotations( self, node: nodes.LocalsDictNodeNG, all_used_type_annotations: dict[str, bool] ) -> None: """Adds to `all_used_type_annotations` all names ever used as a type annotation in the node's (nested) scopes and whether they are only used as annotation. """ for name in node.locals: # If we find a private type annotation, make sure we do not mask illegal usages private_name = None # All the assignments using this variable that we might have to check for # illegal usages later name_assignments = [] for usage_node in node.locals[name]: if isinstance(usage_node, nodes.AssignName) and isinstance( usage_node.parent, (nodes.AnnAssign, nodes.Assign) ): assign_parent = usage_node.parent if isinstance(assign_parent, nodes.AnnAssign): name_assignments.append(assign_parent) private_name = self._populate_type_annotations_annotation( usage_node.parent.annotation, all_used_type_annotations ) elif isinstance(assign_parent, nodes.Assign): name_assignments.append(assign_parent) if isinstance(usage_node, nodes.FunctionDef): self._populate_type_annotations_function( usage_node, all_used_type_annotations ) if isinstance(usage_node, nodes.LocalsDictNodeNG): self._populate_type_annotations( usage_node, all_used_type_annotations ) if private_name is not None: # Found a new private annotation, make sure we are not accessing it elsewhere all_used_type_annotations[ private_name ] = self._assignments_call_private_name(name_assignments, private_name) def _populate_type_annotations_function( self, node: nodes.FunctionDef, all_used_type_annotations: dict[str, bool] ) -> None: """Adds all names used as type annotation in the arguments and return type of the function node into the dict `all_used_type_annotations`. """ if node.args and node.args.annotations: for annotation in node.args.annotations: self._populate_type_annotations_annotation( annotation, all_used_type_annotations ) if node.returns: self._populate_type_annotations_annotation( node.returns, all_used_type_annotations ) def _populate_type_annotations_annotation( self, node: nodes.Attribute | nodes.Subscript | nodes.Name | None, all_used_type_annotations: dict[str, bool], ) -> str | None: """Handles the possibility of an annotation either being a Name, i.e. just type, or a Subscript e.g. `Optional[type]` or an Attribute, e.g. `pylint.lint.linter`. """ if isinstance(node, nodes.Name) and node.name not in all_used_type_annotations: all_used_type_annotations[node.name] = True return node.name # type: ignore[no-any-return] if isinstance(node, nodes.Subscript): # e.g. Optional[List[str]] # slice is the next nested type self._populate_type_annotations_annotation( node.slice, all_used_type_annotations ) # value is the current type name: could be a Name or Attribute return self._populate_type_annotations_annotation( node.value, all_used_type_annotations ) if isinstance(node, nodes.Attribute): # An attribute is a type like `pylint.lint.pylinter`. node.expr is the next level # up, could be another attribute return self._populate_type_annotations_annotation( node.expr, all_used_type_annotations ) return None @staticmethod def _assignments_call_private_name( assignments: list[nodes.AnnAssign | nodes.Assign], private_name: str ) -> bool: """Returns True if no assignments involve accessing `private_name`.""" if all(not assignment.value for assignment in assignments): # Variable annotated but unassigned is not allowed because there may be # possible illegal access elsewhere return False for assignment in assignments: current_attribute = None if isinstance(assignment.value, nodes.Call): current_attribute = assignment.value.func elif isinstance(assignment.value, nodes.Attribute): current_attribute = assignment.value elif isinstance(assignment.value, nodes.Name): current_attribute = assignment.value.name if not current_attribute: continue while isinstance(current_attribute, (nodes.Attribute, nodes.Call)): if isinstance(current_attribute, nodes.Call): current_attribute = current_attribute.func if not isinstance(current_attribute, nodes.Name): current_attribute = current_attribute.expr if ( isinstance(current_attribute, nodes.Name) and current_attribute.name == private_name ): return False return True @staticmethod def same_root_dir( node: nodes.Import | nodes.ImportFrom, import_mod_name: str ) -> bool: """Does the node's file's path contain the base name of `import_mod_name`?""" if not import_mod_name: # from . import ... return True if node.level: # from .foo import ..., from ..bar import ... return True base_import_package = import_mod_name.split(".")[0] return base_import_package in Path(node.root().file).parent.parts def register(linter: PyLinter) -> None: linter.register_checker(PrivateImportChecker(linter))