(root)/
Python-3.11.7/
Lib/
test/
test_netrc.py
       1  import netrc, os, unittest, sys, textwrap
       2  from test.support import os_helper
       3  
       4  try:
       5      import pwd
       6  except ImportError:
       7      pwd = None
       8  
       9  temp_filename = os_helper.TESTFN
      10  
      11  class ESC[4;38;5;81mNetrcTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      12  
      13      def make_nrc(self, test_data):
      14          test_data = textwrap.dedent(test_data)
      15          mode = 'w'
      16          if sys.platform != 'cygwin':
      17              mode += 't'
      18          with open(temp_filename, mode, encoding="utf-8") as fp:
      19              fp.write(test_data)
      20          try:
      21              nrc = netrc.netrc(temp_filename)
      22          finally:
      23              os.unlink(temp_filename)
      24          return nrc
      25  
      26      def test_toplevel_non_ordered_tokens(self):
      27          nrc = self.make_nrc("""\
      28              machine host.domain.com password pass1 login log1 account acct1
      29              default login log2 password pass2 account acct2
      30              """)
      31          self.assertEqual(nrc.hosts['host.domain.com'], ('log1', 'acct1', 'pass1'))
      32          self.assertEqual(nrc.hosts['default'], ('log2', 'acct2', 'pass2'))
      33  
      34      def test_toplevel_tokens(self):
      35          nrc = self.make_nrc("""\
      36              machine host.domain.com login log1 password pass1 account acct1
      37              default login log2 password pass2 account acct2
      38              """)
      39          self.assertEqual(nrc.hosts['host.domain.com'], ('log1', 'acct1', 'pass1'))
      40          self.assertEqual(nrc.hosts['default'], ('log2', 'acct2', 'pass2'))
      41  
      42      def test_macros(self):
      43          data = """\
      44              macdef macro1
      45              line1
      46              line2
      47  
      48              macdef macro2
      49              line3
      50              line4
      51  
      52          """
      53          nrc = self.make_nrc(data)
      54          self.assertEqual(nrc.macros, {'macro1': ['line1\n', 'line2\n'],
      55                                        'macro2': ['line3\n', 'line4\n']})
      56          # strip the last \n
      57          self.assertRaises(netrc.NetrcParseError, self.make_nrc,
      58                            data.rstrip(' ')[:-1])
      59  
      60      def test_optional_tokens(self):
      61          data = (
      62              "machine host.domain.com",
      63              "machine host.domain.com login",
      64              "machine host.domain.com account",
      65              "machine host.domain.com password",
      66              "machine host.domain.com login \"\" account",
      67              "machine host.domain.com login \"\" password",
      68              "machine host.domain.com account \"\" password"
      69          )
      70          for item in data:
      71              nrc = self.make_nrc(item)
      72              self.assertEqual(nrc.hosts['host.domain.com'], ('', '', ''))
      73          data = (
      74              "default",
      75              "default login",
      76              "default account",
      77              "default password",
      78              "default login \"\" account",
      79              "default login \"\" password",
      80              "default account \"\" password"
      81          )
      82          for item in data:
      83              nrc = self.make_nrc(item)
      84              self.assertEqual(nrc.hosts['default'], ('', '', ''))
      85  
      86      def test_invalid_tokens(self):
      87          data = (
      88              "invalid host.domain.com",
      89              "machine host.domain.com invalid",
      90              "machine host.domain.com login log password pass account acct invalid",
      91              "default host.domain.com invalid",
      92              "default host.domain.com login log password pass account acct invalid"
      93          )
      94          for item in data:
      95              self.assertRaises(netrc.NetrcParseError, self.make_nrc, item)
      96  
      97      def _test_token_x(self, nrc, token, value):
      98          nrc = self.make_nrc(nrc)
      99          if token == 'login':
     100              self.assertEqual(nrc.hosts['host.domain.com'], (value, 'acct', 'pass'))
     101          elif token == 'account':
     102              self.assertEqual(nrc.hosts['host.domain.com'], ('log', value, 'pass'))
     103          elif token == 'password':
     104              self.assertEqual(nrc.hosts['host.domain.com'], ('log', 'acct', value))
     105  
     106      def test_token_value_quotes(self):
     107          self._test_token_x("""\
     108              machine host.domain.com login "log" password pass account acct
     109              """, 'login', 'log')
     110          self._test_token_x("""\
     111              machine host.domain.com login log password pass account "acct"
     112              """, 'account', 'acct')
     113          self._test_token_x("""\
     114              machine host.domain.com login log password "pass" account acct
     115              """, 'password', 'pass')
     116  
     117      def test_token_value_escape(self):
     118          self._test_token_x("""\
     119              machine host.domain.com login \\"log password pass account acct
     120              """, 'login', '"log')
     121          self._test_token_x("""\
     122              machine host.domain.com login "\\"log" password pass account acct
     123              """, 'login', '"log')
     124          self._test_token_x("""\
     125              machine host.domain.com login log password pass account \\"acct
     126              """, 'account', '"acct')
     127          self._test_token_x("""\
     128              machine host.domain.com login log password pass account "\\"acct"
     129              """, 'account', '"acct')
     130          self._test_token_x("""\
     131              machine host.domain.com login log password \\"pass account acct
     132              """, 'password', '"pass')
     133          self._test_token_x("""\
     134              machine host.domain.com login log password "\\"pass" account acct
     135              """, 'password', '"pass')
     136  
     137      def test_token_value_whitespace(self):
     138          self._test_token_x("""\
     139              machine host.domain.com login "lo g" password pass account acct
     140              """, 'login', 'lo g')
     141          self._test_token_x("""\
     142              machine host.domain.com login log password "pas s" account acct
     143              """, 'password', 'pas s')
     144          self._test_token_x("""\
     145              machine host.domain.com login log password pass account "acc t"
     146              """, 'account', 'acc t')
     147  
     148      def test_token_value_non_ascii(self):
     149          self._test_token_x("""\
     150              machine host.domain.com login \xa1\xa2 password pass account acct
     151              """, 'login', '\xa1\xa2')
     152          self._test_token_x("""\
     153              machine host.domain.com login log password pass account \xa1\xa2
     154              """, 'account', '\xa1\xa2')
     155          self._test_token_x("""\
     156              machine host.domain.com login log password \xa1\xa2 account acct
     157              """, 'password', '\xa1\xa2')
     158  
     159      def test_token_value_leading_hash(self):
     160          self._test_token_x("""\
     161              machine host.domain.com login #log password pass account acct
     162              """, 'login', '#log')
     163          self._test_token_x("""\
     164              machine host.domain.com login log password pass account #acct
     165              """, 'account', '#acct')
     166          self._test_token_x("""\
     167              machine host.domain.com login log password #pass account acct
     168              """, 'password', '#pass')
     169  
     170      def test_token_value_trailing_hash(self):
     171          self._test_token_x("""\
     172              machine host.domain.com login log# password pass account acct
     173              """, 'login', 'log#')
     174          self._test_token_x("""\
     175              machine host.domain.com login log password pass account acct#
     176              """, 'account', 'acct#')
     177          self._test_token_x("""\
     178              machine host.domain.com login log password pass# account acct
     179              """, 'password', 'pass#')
     180  
     181      def test_token_value_internal_hash(self):
     182          self._test_token_x("""\
     183              machine host.domain.com login lo#g password pass account acct
     184              """, 'login', 'lo#g')
     185          self._test_token_x("""\
     186              machine host.domain.com login log password pass account ac#ct
     187              """, 'account', 'ac#ct')
     188          self._test_token_x("""\
     189              machine host.domain.com login log password pa#ss account acct
     190              """, 'password', 'pa#ss')
     191  
     192      def _test_comment(self, nrc, passwd='pass'):
     193          nrc = self.make_nrc(nrc)
     194          self.assertEqual(nrc.hosts['foo.domain.com'], ('bar', '', passwd))
     195          self.assertEqual(nrc.hosts['bar.domain.com'], ('foo', '', 'pass'))
     196  
     197      def test_comment_before_machine_line(self):
     198          self._test_comment("""\
     199              # comment
     200              machine foo.domain.com login bar password pass
     201              machine bar.domain.com login foo password pass
     202              """)
     203  
     204      def test_comment_before_machine_line_no_space(self):
     205          self._test_comment("""\
     206              #comment
     207              machine foo.domain.com login bar password pass
     208              machine bar.domain.com login foo password pass
     209              """)
     210  
     211      def test_comment_before_machine_line_hash_only(self):
     212          self._test_comment("""\
     213              #
     214              machine foo.domain.com login bar password pass
     215              machine bar.domain.com login foo password pass
     216              """)
     217  
     218      def test_comment_after_machine_line(self):
     219          self._test_comment("""\
     220              machine foo.domain.com login bar password pass
     221              # comment
     222              machine bar.domain.com login foo password pass
     223              """)
     224          self._test_comment("""\
     225              machine foo.domain.com login bar password pass
     226              machine bar.domain.com login foo password pass
     227              # comment
     228              """)
     229  
     230      def test_comment_after_machine_line_no_space(self):
     231          self._test_comment("""\
     232              machine foo.domain.com login bar password pass
     233              #comment
     234              machine bar.domain.com login foo password pass
     235              """)
     236          self._test_comment("""\
     237              machine foo.domain.com login bar password pass
     238              machine bar.domain.com login foo password pass
     239              #comment
     240              """)
     241  
     242      def test_comment_after_machine_line_hash_only(self):
     243          self._test_comment("""\
     244              machine foo.domain.com login bar password pass
     245              #
     246              machine bar.domain.com login foo password pass
     247              """)
     248          self._test_comment("""\
     249              machine foo.domain.com login bar password pass
     250              machine bar.domain.com login foo password pass
     251              #
     252              """)
     253  
     254      def test_comment_at_end_of_machine_line(self):
     255          self._test_comment("""\
     256              machine foo.domain.com login bar password pass # comment
     257              machine bar.domain.com login foo password pass
     258              """)
     259  
     260      def test_comment_at_end_of_machine_line_no_space(self):
     261          self._test_comment("""\
     262              machine foo.domain.com login bar password pass #comment
     263              machine bar.domain.com login foo password pass
     264              """)
     265  
     266      def test_comment_at_end_of_machine_line_pass_has_hash(self):
     267          self._test_comment("""\
     268              machine foo.domain.com login bar password #pass #comment
     269              machine bar.domain.com login foo password pass
     270              """, '#pass')
     271  
     272  
     273      @unittest.skipUnless(os.name == 'posix', 'POSIX only test')
     274      @unittest.skipIf(pwd is None, 'security check requires pwd module')
     275      @os_helper.skip_unless_working_chmod
     276      def test_security(self):
     277          # This test is incomplete since we are normally not run as root and
     278          # therefore can't test the file ownership being wrong.
     279          d = os_helper.TESTFN
     280          os.mkdir(d)
     281          self.addCleanup(os_helper.rmtree, d)
     282          fn = os.path.join(d, '.netrc')
     283          with open(fn, 'wt') as f:
     284              f.write("""\
     285                  machine foo.domain.com login bar password pass
     286                  default login foo password pass
     287                  """)
     288          with os_helper.EnvironmentVarGuard() as environ:
     289              environ.set('HOME', d)
     290              os.chmod(fn, 0o600)
     291              nrc = netrc.netrc()
     292              self.assertEqual(nrc.hosts['foo.domain.com'],
     293                               ('bar', '', 'pass'))
     294              os.chmod(fn, 0o622)
     295              self.assertRaises(netrc.NetrcParseError, netrc.netrc)
     296          with open(fn, 'wt') as f:
     297              f.write("""\
     298                  machine foo.domain.com login anonymous password pass
     299                  default login foo password pass
     300                  """)
     301          with os_helper.EnvironmentVarGuard() as environ:
     302              environ.set('HOME', d)
     303              os.chmod(fn, 0o600)
     304              nrc = netrc.netrc()
     305              self.assertEqual(nrc.hosts['foo.domain.com'],
     306                               ('anonymous', '', 'pass'))
     307              os.chmod(fn, 0o622)
     308              self.assertEqual(nrc.hosts['foo.domain.com'],
     309                               ('anonymous', '', 'pass'))
     310  
     311  
     312  if __name__ == "__main__":
     313      unittest.main()