Giter Site home page Giter Site logo

iydon / of.yaml Goto Github PK

View Code? Open in Web Editor NEW
16.0 16.0 1.0 8.84 MB

Python Interface to OpenFOAM Case (Configured Using YAML)

Home Page: https://pypi.org/project/ifoam

License: GNU General Public License v3.0

Python 94.25% Makefile 0.78% YAML 4.97%
openfoam python yaml

of.yaml's Introduction

GitHub Statistics
Code Statistics

===============================================================================
 Language            Files        Lines         Code     Comments       Blanks
===============================================================================
 Autoconf                9           45           36            0            9
 BASH                   32           98           34           32           32
 Batch                   7          343          289            3           51
 C                      36        4,418        2,599        1,060          759
 C Header               47        3,554        2,507          485          562
 CMake                   1           21           14            0            7
 C++                    13          611          462           40          109
 CSS                     6          493          480           12            1
 Cython                  1           16            7            5            4
 Dockerfile              3          215           95          100           20
 Forge Config            2           38           38            0            0
 FORTRAN Modern          2          201          164            0           37
 Go                      2          140          118            0           22
 JavaScript              2            4            4            0            0
 JSON                   40       21,830       21,828            0            2
 Julia                   2          120          105            0           15
 M4                      2        1,069          927            0          142
 MATLAB                155        6,266        4,650        1,017          599
 Makefile               69        1,272          888           85          299
 Python                836       86,430       74,424        2,102        9,904
 R                       5          256          215            6           35
 ReStructuredText       21        1,046          705            0          341
 Shell                  11          174          101           40           33
 SQL                    19        7,774        7,623           88           63
 SVG                     6          968          883            1           84
 TeX Class              26       14,113       10,567        2,414        1,132
 TeX Definition          3          207          195           12            0
 TeX                   676      328,353      179,029        3,421      145,903
 Plain Text             67      183,640            0      181,202        2,438
 TOML                   18          609          529           15           65
 XML                     1            7            7            0            0
 YAML                   94       37,690       35,842        1,147          701
-------------------------------------------------------------------------------
 HTML                   26        2,542        2,164          322           56
 |- CSS                  5          116          115            0            1
 |- JavaScript           9          461          396           11           54
 (Total)                          3,119        2,675          333          111
-------------------------------------------------------------------------------
 Jupyter Notebooks      11            0            0            0            0
 |- Markdown             7          288            0          259           29
 |- Python              10          370          324           11           35
 (Total)                            658          324          270           64
-------------------------------------------------------------------------------
 Markdown              381       26,913            0       20,808        6,105
 |- C                    1            7            6            0            1
 |- C++                  2           78           63            2           13
 |- HTML                 2           66           66            0            0
 |- JSON                 2        1,096        1,096            0            0
 |- MATLAB               1           62           28           29            5
 |- Markdown             1           51            0           50            1
 |- Python              35        1,965        1,569           82          314
 |- R                    2          214          178           36            0
 |- Rust                 2          269          237            6           26
 |- Shell               23        1,027          979            0           48
 |- SQL                  1            2            2            0            0
 |- TeX                  2           42           35            0            7
 |- XML                  1            8            8            0            0
 |- YAML                 7          263          234           17           12
 (Total)                         32,063        4,501       21,030        6,532
-------------------------------------------------------------------------------
 Rust                  191       20,121       17,145          694        2,282
 |- Markdown            45        8,067           58        5,930        2,079
 (Total)                         28,188       17,203        6,624        4,361
===============================================================================
 Total               2,823      751,597      364,674      215,111      171,812
===============================================================================
  

of.yaml's People

Contributors

iydon avatar vianlee avatar yue-qiang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

of.yaml's Issues

Materials related to remote operation

Related Libraries

Ancient Code

import os
import pathlib
import stat
import subprocess
import textwrap

import paramiko
import toml

from typing import Any, Callable, Dict, Iterator, Optional, Tuple, Union

from .servers import servers


PathLike = Union[str, pathlib.Path]
StandardIO = Tuple[3*(paramiko.channel.ChannelFile, )]


indent = lambda s: textwrap.indent(str(s), 4*' ')


class Config:
    '''้…็ฝฎไฟกๆฏ
    '''
    NONE = 0  # None in toml
    TODO = ''  # todo
    data_fields = ('username', 'password', 'private_key_path')
    meta_fields = ('rsync', )

    def __init__(
        self,
        server: str, software: str, version: str,
        path: PathLike = 'config.toml', encoding: str = 'utf-8',
    ) -> None:
        assertion = lambda s, d: f'Accessible {s}(s): ' + ', '.join(d)
        self._keys = server, software, version
        assert (server:=servers.get(server)), assertion('server', servers)
        assert (software:=server.get(software)), assertion('software', server)
        assert (version:=software.get(version)), assertion('version', software)
        self._main = version  # server-software-version
        self._path = pathlib.Path(path)
        self._path.touch(exist_ok=True)
        self._encoding = encoding
        self._data = toml.loads(self._path.read_text(encoding))
        # ้…็ฝฎๆ–‡ไปถ้ป˜่ฎคๅ€ผ
        self._data.setdefault('meta', {f: self.TODO for f in self.meta_fields})
        self._data \
            .setdefault(self._keys[0], dict()) \
            .setdefault(self._keys[1], dict()) \
            .setdefault(self._keys[2], {f: self.TODO for f in self.data_fields})

    def __getitem__(self, key: str) -> Optional[str]:
        value = self.data.get(key)
        return value if value!=self.NONE else None

    def __str__(self) -> str:
        destination = f'{self["username"]}@{self.host}:{self.port}'
        return f'<Config>{"::".join(self._keys)} {destination}</Config>'

    @property
    def data(self) -> Dict[str, Any]:
        # data = self._data
        # for key in self._keys:
        #     data = data[key]
        # return data
        server, software, version = self._keys
        return self._data[server][software][version]

    @property
    def meta(self) -> Dict[str, Any]:
        return self._data['meta']

    @property
    def host(self) -> str:
        return self._main.host

    @property
    def port(self) -> str:
        return self._main.port

    def input(
        self,
        input: Callable[[str], str] = input, pattern: str = '({}) >> ',
    ) -> 'Config':
        for d1ct in (self.meta, self.data):  # s1mple
            for key, value in d1ct.items():
                if value == self.TODO:
                    d1ct[key] = input(pattern.format(key)) or self.NONE
        return self.save()

    def save(self) -> 'Config':
        self._path.write_text(toml.dumps(self._data), self._encoding)
        return self


class Remote:
    '''่ฟœ็จ‹่ฟžๆŽฅ
    '''
    def __init__(self, config: Config) -> None:
        self._config = config
        self._trans = paramiko.Transport((config._main.host, int(config._main.port)))
        self._ssh = self._sftp = None
        self._path = [pathlib.PureWindowsPath, pathlib.PurePosixPath][config._main.posix]
        # ๅŽๅค„็†
        self._trans.connect(username=config['username'], **self._connect_kwargs())

    def __enter__(self) -> 'Remote':
        return self

    def __exit__(self, *_) -> None:  # type, value, traceback
        self.close()

    def __str__(self) -> str:
        return f'<Remote>\n{indent(self._config)}\n</Remote>'

    @classmethod
    def from_config(cls, *args, **kwargs) -> 'Remote':
        '''ๅฆ‚ๆžœ้œ€ๆŒ‡ๅฎš input ็š„ๅ‚ๆ•ฐ๏ผŒ่ฏทไฝฟ็”จๅฎŒๆ•ดๆž„้€ ๅ‡ฝๆ•ฐ

        - Example:
            >>> with Remote.from_config('sustech_iydon') as remote:
            ...     pass

            >>> with Remote(Config('sustech_iydon')) as remote:
            ...     pass
        '''
        return cls(Config(*args, **kwargs).input())

    @property
    def config(self) -> 'Config':
        return self._config

    @property
    def ssh(self) -> paramiko.SSHClient:
        if self._ssh is None:
            self._ssh = paramiko.SSHClient()
            self._ssh._transport = self._trans
            self._ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        return self._ssh

    @property
    def sftp(self) -> paramiko.SFTPClient:
        if self._sftp is None:
            self._sftp = paramiko.SFTPClient.from_transport(self._trans)
        return self._sftp

    @property
    def Path(self) -> pathlib.Path:
        return self._path

    def close(self) -> None:
        self._ssh and self._ssh.close()  # is not None
        self._sftp and self._sftp.close()
        self._ssh = self._sftp = None

    def copy(
        self,
        local_path: PathLike, remote_path: PathLike, down: bool = True,
    ) -> None:
        '''ๆ‹ท่ดๆ–‡ไปถ

        - Argument:
            - down: local_path<-remote_path if down else local_path->remote_path
        '''
        method = getattr(self.sftp, 'get' if down else 'put')
        method(localpath=str(local_path), remotepath=str(remote_path))

    def exec(self, command: str, encoding: Optional[str] = None) -> Tuple[str, str]:
        '''ssh: exec command
        '''
        _, stdout, stderr = self._exec(command)
        encoding = encoding or self._config._encoding
        return stdout.read().decode(encoding), stderr.read().decode(encoding)

    def exists(self, remote_path_or_directory: PathLike) -> bool:
        '''่ฟœ็จ‹ๆ–‡ไปถๆˆ–ๆ–‡ไปถๅคนๆ˜ฏๅฆๅญ˜ๅœจ
        '''
        try:
            self.sftp.stat(str(remote_path_or_directory))
        except OSError:
            return False
        else:
            return True

    def mkdir(self, remote_directory: PathLike) -> None:
        '''ๆ–ฐๅปบ่ฟœ็จ‹ๆ–‡ไปถๅคน

        - Note:
            - parents=True, exist_ok=True
        '''
        path = self._path(remote_directory) / 'NULL'
        for parent in reversed(path.parents):
            try:
                self.sftp.mkdir(str(parent))
            except OSError:
                pass

    def stat(self, remote_path_or_directory: PathLike) -> paramiko.SFTPAttributes:
        return self.sftp.stat(str(remote_path_or_directory))

    def sync(
        self,
        local_directory: PathLike, remote_directory: PathLike,
        down: bool = True, dry_run: bool = False, **_,  # verify
    ):
        '''rsync ๅ‘ฝไปค
        '''
        local, remote = pathlib.Path(local_directory), self.Path(remote_directory)
        destination = f'{self._config["username"]}@{self._config.host}:{remote}'
        # parts of command
        rsync = self._config.meta['rsync'].format(port=self._config.port)
        options = ['--dry-run'] if dry_run else list()
        from_, to = (destination, local) if down else (local, destination)
        parts = (rsync, *options, from_, to)
        process = subprocess.run(' '.join(map(str, parts)), cwd=os.getcwd(), shell=True)
        assert process.returncode==0, repr(parts)

    def syncpy(
        self,
        local_directory: PathLike, remote_directory: PathLike,
        down: bool = True, dry_run: bool = False, verify: bool = True, **_,
    ) -> None:
        '''Python ๅฎž็Žฐ็š„ๅŒๆญฅ็›ฎๅฝ•

        - Note:
            - ไป…้€š่ฟ‡ๆ ก้ชŒๆ–‡ไปถๅคงๅฐๅˆคๆ–ญๆ˜ฏๅฆไธ€่‡ด๏ผˆๅฏ่ƒฝๅŽ็ปญ่€ƒ่™‘ mtime๏ผ‰

        - See Also
            - `Remote::copy`
        '''
        copy = (lambda l, r, d: print(l, '><'[d], r)) if dry_run else self.copy
        exists, mkdir, order = (
            lambda p: p.exists(), lambda d: d.mkdir(0o777, True, True), lambda *x: x,
        ) if down else (self.exists, self.mkdir, lambda *x: reversed(x))
        to_directory, from_directory = order(
            pathlib.Path(local_directory), self._path(remote_directory)
        )
        stat = lambda p, loc: p.stat() if loc else self.stat(p)
        # from -> to
        directory = to_directory / from_directory.name
        for from_path in self._walk(from_directory, not down):
            to_path = directory / from_path.relative_to(from_directory)
            not dry_run and mkdir(to_path.parent)
            if verify and exists(to_path):
                s1, s2 = stat(to_path, down), stat(from_path, not down)
                if s1.st_size==s2.st_size:  # s1.st_mtime==s2.st_mtime
                    continue
            copy(*order(to_path, from_path), down)

    def walk(self, root: PathLike) -> Iterator[pathlib.Path]:
        '''้ๅŽ†ๆœๅŠกๅ™จๆ–‡ไปถ

        - Example:
            >>> for path in remote.walk(remote.Path(...)):
            ...     pass
        '''
        # assert stat.S_ISDIR(self.sftp.stat(str(self._path(root))).st_mode)
        yield from self._walk(self._path(root), local=False)

    def _connect_kwargs(self) -> Dict[str, Any]:
        if (password:=self._config['password']) is not None:
            return {'password': password}
        if (path:=self._config['private_key_path']) is not None:
            return {'pkey': paramiko.RSAKey.from_private_key_file(path)}
        return dict()

    def _exec(self, command: str) -> StandardIO:
        '''ๅบ•ๅฑ‚ paramiko wrapper
        '''
        return self.ssh.exec_command(command)  # stdin, stdout, stderr

    def _sync_down(self) -> None:
        pass

    def _sync_up(self) -> None:
        pass

    def _walk(self, root: pathlib.Path, local: bool = True) -> Iterator[pathlib.Path]:
        if local:  # ๆœ‰็Žฐๆˆๆ–นๆณ•๏ผŒ้ฟๅ…้€’ๅฝ’
            for dirname, _, filenames in os.walk(root):
                yield from map(pathlib.Path(dirname).__truediv__, filenames)
        else:
            # assert isinstance(root, self._path)
            for attr in self.sftp.listdir_attr(str(root)):
                path = root / attr.filename
                yield from (
                    self._walk(path, local=False) if stat.S_ISDIR(attr.st_mode)
                    else (path, )
                )


class Scheduler:
    '''ๆœๅŠก่ฐƒๅบฆๅ™จ
    '''
    def __init__(self, config: Config) -> None:
        self._remote = Remote(config)

    def __enter__(self) -> 'Scheduler':
        return self

    def __exit__(self, *_) -> None:
        self._remote.close()

    def __str__(self) -> str:
        return f'<Scheduler>\n{indent(self._remote)}\n</Scheduler>'

    @classmethod
    def from_config(cls, *args, **kwargs) -> 'Scheduler':
        '''
        - See Also:
            - `Remote::from_config`
        '''
        return cls(Config(*args, **kwargs).input())

    @property
    def config(self) -> 'Config':
        return self._remote._config

    @property
    def remote(self) -> 'Remote':
        return self._remote

YAML ๆทปๅŠ  OpenFOAM ็‰ˆๆœฌๅท

่™ฝ็„ถ็›ฎๅ‰ๅ‚่€ƒ็š„็ฎ—ไพ‹ๅ‡ๆฅ่‡ช OpenFOAM-7๏ผŒไฝ†ๆ˜ฏๆœ‰ๅฆ‚ไธ‹ๆทปๅŠ ็‰ˆๆœฌๅท็š„ๅŽŸๅ› ๏ผš

  • ๆ–นไพฟ Alltest ๆ—ถ้€‰็”จไธๅŒ็Žฏๅขƒ
  • ่ฎฐๅฝ•็ฎ—ไพ‹็š„ meta ไฟกๆฏ

ๅฆ‚ๆžœ่ƒฝๅœจ YAML ๆ–‡ไปถๅไธŠไนŸๅŒบๅˆ†็‰ˆๆœฌๅทๅฐฑๆ›ดๅฅฝไบ†๏ผŒ่ฟ™ๆ ทไธ€ๆ—ฆๆถ‰ๅŠๅˆฐไธๅŒ็‰ˆๆœฌ็š„็ฎ—ไพ‹ๆ—ถๆ–‡ไปถๅไธ่‡ณไบŽ้‡ๅคใ€‚

Improve format of the code

  • Trim trailing whitespace
  • Convert indentation to spaces
  • Add space after comma and comment
  • End the file with a newline
  • ...

python3.7 compatibility issues

AttributeError: module 'functools' has no attribute 'cached_property'
AttributeError: module 'functools' has no attribute 'singledispatchmethod'

Move cases to a new repository

<repository>
โ”œโ”€โ”€ README.md
โ”œโ”€โ”€ OpenFOAM
โ”‚ย ย  โ”œโ”€โ”€ README.md
โ”‚ย ย  โ”œโ”€โ”€ 7
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ ...
โ”‚ย ย  โ”œโ”€โ”€ 9
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ ...
โ”‚ย ย  โ””โ”€โ”€ ...
โ”œโ”€โ”€ third_party
โ”‚ย ย  โ”œโ”€โ”€ README.md
โ”‚ย ย  โ”œโ”€โ”€ BasicOpenFOAMProgrammingTutorials
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ ...
โ”‚ย ย  โ”œโ”€โ”€ openfoam_tutorials
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ ...
โ”‚ย ย  โ””โ”€โ”€ ...
โ””โ”€โ”€ ...

List some OpenFOAM related projects

add `CHANGELOG`

  • v0.3
    • add partial support for standard list
    • YAML file with multiple documents (meta, foam, static)
  • v0.4
    • rewrite single file to package form
    • parse command line parameters with click
  • v0.5
    • add version handling

embed binary data in YAML files as multiple documents

name: gen6DoF
type: 7z
data: static/sloshingTank3D6DoF-gen6DoF.7z

---
meta:
    static:
        -
            name: gen6DoF
            type: embed/7z
            data: static/sloshingTank3D6DoF-gen6DoF.7z
---
gen6DoF: !!binary |
    N3q8ryccAAQNYUZhXwoAAAAAAABaAAAAAAAAACx8rOngGgAKV10ABQ0pPROkhrs7DAcooPWoEZTr
    l5BPTr5w8ZRQP6Jo5ffp6lYIiraB41qo6NwuCfBUHn5xarJflMZju3kb5t1mirtiegf3VxGG4Lkw
    pe8d2R6Nq2GqXiBLd/VK1HNQ7WhuvGwREVEuwa7UBUSbvMSGeR0qOeOUKwwn982zpLicZBqCWY3R
    wUtUMpN8XiPJuyWTTudA4ahMoNW9pSluy1k+P+3TvZb6Is3gJ3mMRq7ANsMkyKiDWsqKsGlBFRwH
    7HppNnXfsrtllyh2sbWqP254RZmT+ytz/X+IuVFGQyLaCMSlkjk70T/6drP/CsE1+ybvqlpduVdB
    q7HSRDxC1uP9rY039pjV/9YF4GlEe18qXN+CavsfU0JZUJUrALiBRo3Y68N1dG8ghHb3JIrvEuJ6
    QSTXigXyqB+uZWf3FRs4hZgf9aa/TVKFCfYGhGRCgB7AQTBOWHl44WsB46golZL4gZNOx0uu9cQX
    TECTVh57ZXy4fqq/cKZRHFGM1QRcvIN2KmTwblccZuwW3vsdpsC8OBdS5eB1xDVpgvCHawHtXcBi
    g2cfzHUx/IuJ3i6qu9yLPIA+AtQ/vVl2KbhE1cdoYAlNbOZcXYAdhKcVwOt2XZz1xlHsjkeVntjs
    SWxjdsQZ+/gvHwV5yS3lW2PoRqCfaIqIrDaCWU2ayPw9QQK2hgIDKBsLQ2ufHPZFkbq9mnxgagz4
    Hd5Km8sc/1HuG6HZVHCGs0Y4f7ikFO+rqUOkSe6q6zg+oytkkmsye2RTWwFitZ570781LsOq2gZ8
    3C48P6YoVf59BXtGPAzR1NY2g87Y9lxFabecpwSPFdHGkJ0Lc15sfVlAoF3/fIUXvvzuKr7QkPNQ
    jxB7emOeSoMlmS4w7XfOKUegpKFdonuq+hY2VTcs8ty1dGJXZcr/FWHDItj8igLmmWj0+2qzvQqJ
    AJVqcTg2i0q9Jhqnmcc7PQdWr1b9vI8V2LgHEfxuzl7yRaXIIF8IwAH5DVUaMZUoUF366NSf+m3R
    h/zDU80T2VibylgG252tsUTBbMqNB9T7GWiEBj6y6ugPkLfzziQbo2fqU5rVnGORYJvnyBgfJ1DK
    aei5l7tDZGAHXuDT2Y64QDMlopOB2CZ+W4p59pjZWiBhlBwwv9F7zQKoTPjVH9utYwBEwVSrS3KL
    GmYQW3rbx0guChBOZijqkyw2iUuDiGzwYguP/Et3ild4sSEYa6rhq0V3DKWH6g2lGs3/woBryKa2
    2PM92SWDg2qhD97UV7+8ctIe+eE2sFhqMtIjeF8tVmyh6WiSilPZ8YALRX+42+8QW8ky6N6WzrRr
    fB+5i1X37DMUzfB77/vh6PYYaPN/wfgwjFmXq079rMay+azu4ZecTjuM7PWZgGidnsMq/9gEDGZi
    DBG0atIQ81oivTPSLnioyhwThGQyh0nL4xXx6/0hsifqvZFIdJ1OHspf8iRr9YVG7xkRH7hHzPbS
    75+9EN00hTMqv2J6+1JM/Q/xZuSUvOF3gcaGT0XF5BSp9Fyna461MceqzLIG/zZme55fYtFQSsw5
    RAZQeOk4xUoMpI2quiyoRsZZjiMV5NofD9URc53HCpiLmC6WWJzjSF1l3gEf9rMAQ8h/pg2QW5y2
    ixb1HFxm3tWWuqtp7CPDLSYAYPiijGuTFm6JQrz1XV5RaJ+brDj08q0zpS3Qaa8vfGXbhO9GM8qV
    IGIVXvss2ExZMY54CeCqeKMQ0POQDQm3f+pFZJqITWyNr8fzjtRA40SPUxww8+OhXptwUbnPD6k3
    1dy8C8iVswoPka4Isyoa01Tzqo0t1nS3pzAd8wdg9R+cL2X0XSQxXTH7l9Q7of2n+q+aidWS8hrC
    DGzTy+YAiI4K0qzCMXBIwFG6GJGiX425huZ/r8wAbu3p592XsGeC0C5spqu4mRjA15imL+ng+p3s
    j21V0gdheISai2fyZtK666EbJIvu8qNnYd3UT5rBfmFl3k5siPviBsuHXPKDJ9H88jWBq52bXl+V
    Zuo1LGHI3F74VotkWtslfSJVQB+0oX9QEPXFcvtDFBszEW3zwOUJXNCGBQIFxvwnKYqyGiI1yGIU
    vtXh8NfQp04Ennpi+SXP9q/mVFu/loG9f+7uZOHVzbBlivaK5UzKD7531ZzHrIOycZxWb16AnisU
    CiZXeIDYXUhyO8pzyP8Qx2wHMXX5F3AOfP1PpmhMY+rdWwd0Qlmi49wWLRCzyeVSDD8gY4VPpBrs
    FNFvfOxEWneTzEjAm8XiTIg5RNYMsHxqxwb8CEySrYIATiwD6IBiwFFD0Id0bLehBsnoBsCRpSws
    dayVVgWVTdeyMZV4F6NnbjBwb++wDaVuMlwc9JRln0jolK3OWSR8WtqxdrjCG7jw514JDoOi9/js
    8I68T951x0hBDduVQ/chIwVkEcKnpw0rrQ/hgZahAJLcdDV72WvkQN+FPASim7D7mwsQPinECN6S
    dV6jdD5ZoNhJVVzjk2ILyc8HSp+PfIUPjbrd8OHf5zuZVSM7lB2D7pYjGkkocL7PIqi/L/JUJy/j
    NHySWdheskgT4Fc7LJyoXfu6LqxQY1nvpCOZipYrX2X1JJfgVXxqu5xiS4icJ1pmtblhrb4Xjgul
    3YPOIEK7CrZ9UePvK4ReUmdRjPeos0pXIEGF2EUqrg4g5ZmwsBQ84w6ufoOyd/MOPZ2DYPx4vck8
    Yv7RWMeBefq2gEMWGwdPdmaNdUuJam6Xu7TLzKKkKuB15uUlgHujj96PZJd3c0GfCD+i+j2Nf9LB
    4ro8sX8j330mnzP/VB0wZIXeAwCAgKba/q1GKalb7bL1DxyHVV2Og4jZkOaJ4Yyxh7LOlTS7IOM+
    0FwpQuJGJ4n/8FeAO+z5LPkFHx/E6ZpKGl2kWkce+Km1+1Rt7CnEL+AIca5rvmO4TqIziQoRMcJe
    dC2IZKAKpFc0mShQ5JgaKMPb2B3CJJdysEi/TOtPZOwjk/LJ9fwf4GupxvMZ2ZIIccsC5IGCQHCt
    54LxGm97oFcwMrH3EVvhcKPfSCkKcBIrcHeXOIranttQlMMiZ+dB53Ojxahs/8C+RigIKUoTi4vt
    3rj95P/inoN5vKbwu9qRNhqXszNvhAwd8ws1qF9uHKQJM+R7ExPJu5muoPJep75sYDXsHzPRVaYZ
    HZMyg5Xg85fQ8q9zQGAO0JOXbhsaENS1lxFBJW44I9+A4WKTIzCRf28e0opO1a1f6oOoPJQ04/du
    jEWE5mw2JRuENl++xo1jp9leInKNNx1ebd+oBqjqAGxc5/ZHUkKpGMPuC14GsGnOn1ORFxzzVyBE
    kM8s0BYohhnrL/vXk6N7b4XkCKtwzmqM8VztIkABbkkyw58//YZ6t2naxPO2LRkd8GoMOuyeIToF
    EDjfQHZYZGsmC53Bf0fvVl+EdUc++zJNt04ss3FKCH891R+hCeAWHhpHqLNLMjSgdIq9GL7ScPSq
    CG+5i47aqN78SkRfeUz/NT8LX7xdCcR6m0kK0VBcHmcvwYhg/eR0OoBuOHR7hWGFn+oljorPVdNP
    Jt4GbvJLAAABBAYAAQmKXwAHCwEAASEhAQIMmgEACAoBeHU+yAAABQEZCgAAAAAAAAAAAAAREwA2
    AEQAbwBGAC4AZABhAHQAAAAZABQKAQDLI/16ZAbYARUGAQAgAAAAAAA=
---

Also consider replacing type path with path/text, 7z with path/7z

add `Alltest`

Project uses automated testing instead of manual testing

Put loader and dumper together

Code from ihpc:

__all__ = ['dumper', 'loader']


import json
import pathlib as p
import pickle

from ..base.lib import tomlkit, yaml
from ..base.type import Document, Path


class dumper:
    '''Dumper for json, pickle, toml, yaml'''

    _mapper = {
        ('json', ): lambda doc: json.dumps(doc).encode(),
        ('pickle', 'pkl'): lambda doc: pickle.dumps(doc),
        ('toml', ): lambda doc: tomlkit.dumps(doc).encode(),
        ('yaml', 'yml'): lambda doc: yaml.dump(doc).encode(),
    }

    @classmethod
    def to_bytes(cls, document: Document, type: str = 'json') -> bytes:
        for types, dumps in cls._mapper.items():
            if type in types:
                return dumps(document)
        raise Exception(f'"{type}" is not a valid type string')

    @classmethod
    def to_string(cls, document: Document, type: str = 'json') -> str:
        return cls.to_bytes(document, type).decode()

    @classmethod
    def to_path(cls, document: Document, path: Path) -> p.Path:
        path = p.Path(path)
        path.write_bytes(cls.to_bytes(document, path.suffix[1:]))
        return path


class loader:
    '''Loader for json, pickle, toml, yaml'''

    _mapper = {
        ('json', ): json.loads,
        ('pickle', 'pkl'): pickle.loads,
        ('toml', ): tomlkit.loads,
        ('yaml', 'yml'): yaml.load,
    }

    @classmethod
    def auto_from_bytes(cls, content: bytes) -> Document:
        for loads in cls._mapper.values():
            try:
                return loads(content)
            except Exception:
                pass
        raise Exception(f'Unable to recognize content type')

    @classmethod
    def auto_from_string(cls, content: str) -> Document:
        return cls.auto_from_bytes(content.encode())

    @classmethod
    def from_bytes(cls, content: bytes, type: str = 'json') -> Document:
        for types, loads in cls._mapper.items():
            if type in types:
                return loads(content)
        raise Exception(f'"{type}" is not a valid type string')

    @classmethod
    def from_string(cls, content: str, type: str = 'json') -> Document:
        return cls.from_bytes(content.encode(), type)

    @classmethod
    def from_path(cls, path: Path) -> Document:
        path = p.Path(path)
        return cls.from_bytes(path.read_bytes(), path.suffix[1:])

Migrate properties to Foam class

Because there is no need to save to get these properties.

@f.cached_property
def application(self) -> str:
return self._foam['foam']['system', 'controlDict', 'application']
@f.cached_property
def number_of_processors(self) -> int:
try:
return self._foam['foam']['system', 'decomposeParDict', 'numberOfSubdomains']
except:
return 1

Version tags are too messy

ไธๅฝฑๅ“ๅ…ผๅฎนๆ€ง็š„ๅฐไฟฎๆ”นๅชๆ”นๅ˜ๅฐ็‰ˆๆœฌๅท๏ผŒไพ‹ๅฆ‚ไปŽ 0.7.1 ่ทณ่‡ณ 0.7.2๏ผŒ็ญ‰ๅˆฐๆœ€ๅŽๅ‡บ็Žฐๅฝฑๅ“ๅ…ผๅฎนๆ€ง็š„ๅคงไฟฎๆ”นๆ—ถ๏ผŒๅ…ˆๆทปๅŠ  v0.7 ็š„ๆ ‡็ญพ๏ผŒ้ข„็คบ 0.7.* ็‰ˆๆœฌๅทฒ็ป็ป“ๆŸ๏ผŒๅ†ๅฐ†็‰ˆๆœฌๅท่ทณ่‡ณ 0.8.0ใ€‚ไปฅๆญค็ฑปๆŽจใ€‚

่‡ณไบŽ https://github.com/iydon/of.yaml/blob/main/CHANGELOG.md ็š„ไฟฎๆ”น๏ผŒๅœจๆฒกๆœ‰ๆ ‡็ญพๅ‰ไธไธบ็‰ˆๆœฌๆทปๅŠ ๆ ‡็ญพ่ถ…้“พๆŽฅใ€‚

Dynamic load third-party libraries

import typing as t

class Foam:
    @property
    def py7zr(self) -> t.Optional[t.Any]:
        try:
            import py7zr
        except ImportError:
            py7zr = None
        return py7zr

Use mypy to check static types

Compare major version only

It is recommended to compare major version only, this allows you to change only the minor version each time you make a minor change that does not affect compatibility, making it easy to perform version control.

of.yaml/foam/core.py

Lines 41 to 44 in 4f71828

if version < current:
warnings.warn('Forward compatibility is not yet guaranteed')
elif version > current:
warnings.warn('Backward compatibility is not yet guaranteed')

`dictToFoam` executable binary file

Rust

[package]
name = "dictToFoam"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
compress-tools = "0.12.2"
yaml-rust = "0.4"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.